封装可以隐藏实现细节,使得代码模块化,继承可以扩展已存在的模块,它们目的都是为了:代码重用。而多态是为了实现另一个目的:接口重用。
封装是面向对象的特征之一,是对象和类概念的主要特性。封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。一旦定义了一个对象的特性,则有必要决定这些特性的可见性。
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装好处:
1.将变化隔离;
2.便于使用。
3.提高重用性。
4.提高安全性。
封装原则:
将不需要对外提供的内容都隐藏起来。
把属性都隐藏,提供公共方法对其访问。
我们可以通过封装使一部分成员充当类与外部的接口,而将其它的成员隐藏起来,这样就限制了外部对成员的访问,也使不同类之间的相互影响度降低
继承优点:
1,提高了代码的复用性。
2,让类与类之间产生了关系。有了这个关系,才有了多态的特性。
1,多态的体现
父类的引用指向了自己的子类对象。
父类的引用也可以接收自己的子类对象。
2,多态的前提
必须是类与类之间有关系。要么继承,要么实现。
通常还有一个前提:存在覆盖。
3,多态的好处
多态的出现大大的提高程序的扩展性。
4,多态的弊端
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
重载,是指允许存在多个同名方法,而这些方法的参数不同。重载的实现是:编译器根据方法不同的参数表
,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期
就绑定了。
C++, 子类中若有同名函数则隐藏父类的其他同名函数,即子类如果有同名函数则不能继承父类的重载。
重载,是在编译阶段 便已确定具体的代码。对同名不同参数的 方法的调用。
多态:是指子类重新定义父类的虚方法(virtual,abstract)。当子类重新定义了父类的虚方法后,父类根据
赋给它的不同的子类,动态调用属于子类的该方法,这样的方法调用在编译期间是无法确定的
是指子类重新定义父类的虚方法(virtual,abstract)。当子类重新定义了父类的虚方法后,父类根据
赋给它的不同的子类,动态调用属于子类的该方法,这样的方法调用在编译期间是无法确定的。
而对于多态,只有等到方法调用的那一刻,编译器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。
对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;
,封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。
简而言之:
- 有virtual才可能发生动态多态现象
- (无virtual)调用就按原类型调用
令人迷惑的隐藏规则
隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
- 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆,重载是在同一个类中,而隐藏涉及派生类与基类)。
- 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆,覆盖有virtual关键字)。
-
令人迷惑的隐藏规则
隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
- 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆,重载是在同一个类中,而隐藏涉及派生类与基类)。
- 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆,覆盖有virtual关键字)
-
C++虚函数
虚函数: 就是允许被其子类重新定义的成员函数,子类重新定义父类虚函数的做法,可实现成员函数的动态覆盖(Override)。
纯虚函数: 是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”
virtual void funtion()=0
抽象类: 包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能进行实例化。
纯虚函数的作用:
- 为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
- 在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;
),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。