C++基础---面向对象

1. 面向对象

1.1 面向对象的定义

  • 面向对象:Object Oriented,简称OO。
  • 面向对象:是一种思想,是一种程序设计范型,是一种程序开发的方法。
  • 面向对象:是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。
  • 面向对象方法:是一种把面向对象的思想应用于软件开发过程中,指导开发活动的系统方法,是建立在“对象”概念基础上的方法学。
  • 面向对象的概念和应用:已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理结构、CAD技术、人工智能等领域。
    注:面向对象是专指在程序设计中采用封装、继承、多态等设计方法。

1.2 “面向过程”和“面向对象”的区别

  • “面向过程”就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
    例子:可以拿生活中的实例来理解面向过程与面向对象,例如五子棋,面向过程的设计思路就是首先分析问题的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用不同的方法来实现。
  • 如果用“面向对象”的设计思想来解决问题。面向对象的设计则是从另外的思路来解决问题。面向对象是以功能来划分问题,而不是步骤。
    例子:整个五子棋可以分为1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。可以明显地看出,同样是绘制棋局,这样的行为在面向过程的设计中分散在了多个步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。

1.3 “面向对象”和“基于对象”的区别

  • 一种语言要称为面向对象语言,必须支持面向对象几个主要的概念。根据支持程度的不同,通常所说的面向对象语言可以分成两类:基于对象的语言和面向对象的语言。
  • 基于对象的语言: Ada(典型)、Alphard、CLU、Euclid、Modula等。
  • 面向对象的语言: C++、Java、C#、Objective-C等。
  • “面向对象”和“基于对象”都实现了“封装”的概念。
  • “面向对象”实现了“继承和多态”,而“基于对象”没有实现这些。“面向对象”的三大特点(封装,继承,多态)缺一不可。而“基于对象”是使用对象,但是无法利用现有的对象模板产生新的对象类型,继而产生新的对象,也就是说“基于对象”没有继承的特点。而“多态”表示为父类类型的子类对象实例,没有了继承的概念也就无从谈论“多态”。
  • 很多流行技术都是基于对象的,它们使用一些封装好的对象,调用对象的方法,设置对象的属性。但是它们无法让程序员派生新对象类型。他们只能使用现有对象的方法和属性。所以当你判断一个新的技术是否是面向对象的时候,通常可以使用后两个特性来加以判断。
    注:没有复杂的需求的时候,基于过程也没什么不对,面向过程也没什么不对,实用是压倒一切的因素。

1.4 面向对象的三要素/三特征

  • 封装/封装性(Encapsulation):
    (1)封装:是一种信息隐蔽技术,体现于类的说明,使数据更安全,是面向对象的重要特性。使数据和加工该数据的方法(函数)封装为一个整体。以实现独立性很强的模块,使得用户只能见到对象的外特性(对象能接受哪些消息,具有那些处理能力),而对象的内特性(保存内部状态的私有数据和实现加工能力的算法)对用户是隐蔽的。
    (2)封装的目的:在于把对象的设计者和对象者的使用分开,使用者不必知晓行为实现的细节,只须用设计者提供的消息来访问该对象。
    (3)封装的总结:
    这里写图片描述
    注:
    ⑴对象唯一性:每个对象都有自身唯一的标识,通过这种标识,可找到相应的对象。在对象的整个生命期中,它的标识都不改变,不同的对象不能有相同的标识。
    ⑵抽象性:抽象性是指将具有一致的数据结构(属性)和行为(操作)的对象抽象成类。一个类就是这样一种抽象,它反映了与应用有关的重要性质,而忽略其他一些无关内容。任何类的划分都是主观的,但必须与具体的应用有关。
  • 继承/继承性(Inheritance):
    (1)继承:子类自动共享父类之间数据和方法的机制。它由类的派生功能体现。一个类直接继承其它类的全部描述,同时可修改和扩充。具有传递性和单根性。如果B类继承了A类,而C类又继承了B类,则可以说,C类在继承了B类的同时,也继承了A类,C类中的对象可以实现A类中的方法。
    (2)继承的目的:支持系统的可重用性,从而达到减少代码量的作用,而且还促进系统的可扩充性
    (3)继承的总结:
    这里写图片描述
    注:子类继承父类,可以继承父类的方法及属性,实现了多态以及代码的重用,因此也解决了系统的重用性和扩展性,但是继承破坏了封装,因为他是对子类开放的,修改父类会导致所有子类的改变,因此继承一定程度上又破坏了系统的可扩展性,所以继承需要慎用,只有明确的IS-A关系才能使用,同时继承在在程序开发过程中重构得到的,而不是程序设计之初就使用继承,很多面向对象开发者滥用继承,结果造成后期的代码解决不了需求的变化了。因此优先使用组合,而不是继承,是面向对象开发中一个重要的经验。
  • 多态/多态性(Polymorphism):
    (1)多态:即接口的多种不同的实现方式,接口是对行为的抽象。
    (2)多态的目的:对象根据所接收的消息而做出动作。同一消息为不同的对象接受时可产生完全不同的行动,这种现象称为多态性。即用户可发送一个通用的信息,而将所有的实现细节都留给接受消息的对象自行决定,如果是同一消息即可调用不同的方法。
    (3)多态性的实现:受到继承性的支持,利用类继承的层次关系,把具有通用功能的协议存放在类层次中尽可能高的地方,而将实现这一功能的不同方法置于较低层次,这样,在这些低层次上生成的对象就能给通用消息以不同的响应。在OOPL中可通过在派生类中重定义基类函数(定义为重载函数或虚函数)来实现多态性
    (4)多态的总结:
    这里写图片描述
    注:多态性包含编译时的多态性、运行时的多态性两大类。 即:多态性也分静态多态性和动态多态性两种。
    (1)静态多态性:指定义在一个类或一个函数中的同名函数,它们根据参数表(类型以及个数)区别语义,并通过静态联编实现,例如,在一个类中定义的不同参数的构造函数。
    (2)动态多态性:指定义在一个类层次的不同类中的重载函数,它们一般具有相同的函数,因此要根据指针指向的对象所在类来区别语义,它通过动态联编实现。在用户不作任何干预的环境下,类的成员函数的行为能根据调用它的对象类型自动作出适应性调整,而且调整是发生在程序运行时,这就是程序的动态多态性。即,发出同样的消息被不同类型的对象接收时,有可能导致完全不同的行为。

1.5 面向对象的五原则/七原则

  • 单一职责原则:SRP–Single-Responsibility Principle,简称SRP(*)
    (1)说明:就一个类而言,应该只专注于做一件事和仅有一个引起它变化的原因。所谓职责,我们可以理解他为功能,就是设计的这个类功能应该只有一个,而不是两个或更多。也可以理解为引用变化的原因,当你发现有两个变化会要求我们修改这个类,那么你就要考虑撤分这个类了。因为职责是变化的一个轴线,当需求变化时,该变化会反映类的职责的变化。
    (2)注意:
    —–一个合理的类,应该仅有一个引起它变化的原因,即单一职责。
    —–在没有变化征兆的情况下应用SRP或其他原则是不明智的。
    —–在需求实际发生变化时就应该应用SRP等原则来重构代码。
    —–使用测试驱动开发会迫使我们在设计出现臭味之前分离不合理代码。
    —–如果测试不能迫使职责分离,僵化性和脆弱性的臭味会变得很强烈,那就应该用Facade或Proxy模式对代码重构;SRP优点:消除耦合,减小因需求变化引起代码僵化。
    (3)单一职责原则—SRP的总结:
    这里写图片描述
  • 开放-封闭原则:Open-Closed Principle,简称OCP(*)
    (1)说明:对扩展开放,对修改关闭。
    (2)优点:按照OCP原则设计出来的系统,降低了程序各部分之间的耦合性,其适应性、灵活性、稳定性都比较好。当已有软件系统需要增加新的功能时,不需要对作为系统基础的抽象层进行修改,只需要在原有基础上附加新的模块就能实现所需要添加的功能。增加的新模块对原有的模块完全没有影响或影响很小,这样就无须为原有模块进行重新测试。
    (3)如何实现“开-闭”原则:在面向对象设计中,不允许更改的是系统的抽象层,而允许扩展的是系统的实现层。换言之,定义一个一劳永逸的抽象设计层,允许尽可能多的行为在实现层被实现。
    (4)解决问题关键:在于抽象化,抽象化是面向对象设计的第一个核心本质。 对一个事物抽象化,实质上是在概括归纳总结它的本质。抽象让我们抓住最最重要的东西,从更高一层去思考。这降低了思考的复杂度,我们不用同时考虑那么多的东西。换言之,我们封装了事物的本质,看不到任何细节。 在面向对象编程中,通过抽象类及接口,规定了具体类的特征作为抽象层,相对稳定,不需更改,从而满足“对修改关闭”;而从抽象类导出的具体类可以改变系统的行为,从而满足“对扩展开放”。 对实体进行扩展时,不必改动软件的源代码或者二进制代码。关键在于抽象。
    (5)开放-封闭原则—OCP的总结:
    这里写图片描述
  • 里氏替换原则:Liskov Substitution Principle,简称LSP(*)
    (1)说明:子类型必须能够替换它们的基类型。一个软件实体如果使用的是一个基类,那么当把这个基类替换成继承该基类的子类,程序的行为不会发生任何变化。软件实体察觉不出基类对象和子类对象的区别。
    (2)优点:可以很容易的实现同一父类下各个子类的互换,而客户端可以毫不察觉。
    (3)里氏替换原则—LSP的总结:
    这里写图片描述
  • 依赖倒置原则:Dependence Inversion Principle,简称DIP(*)
    (1)说明:要依赖于抽象,不要依赖于具体。客户端依赖于抽象耦合。抽象不应当依赖于细节,细节应当依赖于抽象,要针对接口编程,不针对实现编程。
    (2)优点:使用传统过程化程序设计所创建的依赖关系,策略依赖于细节,这是糟糕的,因为策略受到细节改变的影响。依赖倒置原则使细节和策略都依赖于抽象,抽象的稳定性决定了系统的稳定性。
    (3)怎样做到依赖倒置:以抽象方式耦合是依赖倒转原则的关键。抽象耦合关系总要涉及具体类从抽象类继承,并且需要保证在任何引用到基类的地方都可以改换成其子类,因此,里氏代换原则是依赖倒转原则的基础。 在抽象层次上的耦合虽然有灵活性,但也带来了额外的复杂性,如果一个具体类发生变化的可能性非常小,那么抽象耦合能发挥的好处便十分有限,这时可以用具体耦合反而会更好。
    (4)层次化:所有结构良好的面向对象构架都具有清晰的层次定义,每个层次通过一个定义良好的、受控的接口向外提供一组内聚的服务。
    (5)依赖于抽象:建议不依赖于具体类,即程序中所有的依赖关系都应该终止于抽象类或者接口。尽量做到,任何变量都不应该持有一个指向具体类的指针或者引用;任何类都不应该从具体类派生;任何方法都不应该覆写它的任何基类中的已经实现的方法。
    (6)依赖倒置原则—DIP的总结:
    这里写图片描述
  • 接口隔离原则:Interface Segregation Principle,简称ISP(*)
    (1)说明:使用多个专一功能的接口比使用一个的总接口总要好。从一个客户类的角度来讲:一个类对另外一个类的依赖性应当是建立在最小接口上的。过于臃肿的接口是对接口的污染,不应该强迫客户依赖于它们不用的方法。
    (2)优点:会使一个软件系统功能扩展时,修改的压力不会传到别的对象那里。
    (3)如何实现接口隔离原则:不应该强迫用户依赖于他们不用的方法,利用委托分离接口和多继承分离接口。
    (4)接口隔离原则—ISP的总结:
    这里写图片描述
  • 合成/聚合复用原则或合成复用原则:Composite/Aggregate Reuse Principle or Composite Reuse Principle,简称CARP or CRP
    (1)说明:如果新对象的某些功能在别的已经创建好的对象里面已经实现,那么尽量使用别的对象提供的功能,使之成为新对象的一部分,而不要自己再重新创建。新对象通过向这些对象的委派达到复用已有功能的。 简而言之,要尽量使用合成/聚合,尽量不要使用继承。
    (2)优点:
    —–新对象存取成分对象的唯一方法是通过成分对象的接口。
    —–这种复用是黑箱复用,因为成分对象的内部细节是新对象所看不见的。
    —–这种复用支持包装。
    —–这种复用所需的依赖较少。
    —–每一个新的类可以将焦点集中在一个任务上。
    —–这种复用可以在运行时间内动态进行,新对象可以动态的引用与成分对象类型相同的对象。
    —–作为复用手段可以应用到几乎任何环境中去。
    (3)缺点:就是系统中会有较多的对象需要管理。
  • 迪米特原则或最少知识原则:Law of Demeter or Least Knowledge Principle,简称LOD or LKP
    (1)说明:对象与对象之间应该使用尽可能少的方法来关联,避免千丝万缕的关系。
    (2)如何实现迪米特法则:迪米特法则的主要用意是控制信息的过载。
    (3)在将其运用到系统设计中应注意以下几点:
    —–在类的划分上,应当创建有弱耦合的类。类之间的耦合越弱,就越有利于复用。
    —–在类的结构设计上,每一个类都应当尽量降低成员的访问权限。一个类不应当public自己的属性,而应当提供取值和赋值的方法让外界间接访问自己的属性。
    —–在类的设计上,只要有可能,一个类应当设计成不变类。
    —–在对其它对象的引用上,一个类对其它对象的引用应该降到最低。
    注:打星号(*)的是属于面向对象的五原则的。

1.6 面向对象的六视点

  • 复用(Reusibility)
    这里写图片描述
    这里写图片描述
  • 扩展(Extensibility)
    这里写图片描述
  • 分离(Separability)
    这里写图片描述
    这里写图片描述
  • 变化(Change)
    这里写图片描述
    这里写图片描述
  • 简约(Simplicity)
    这里写图片描述
    这里写图片描述
  • 一致(Coherance)
    这里写图片描述

参考文献:
[1] 百度搜索关键字:面向对象、面向过程、基于对象、面向对象三要素、面向对象七原则、面向对象六视点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值