多态概念和定义
1.概念
就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。
比如:有些航空公司卖票,同一张飞机票,安卓1000,苹果1200.
2.定义
条件:
- 虚函数的重写 ——> 父子类中的两个虚函数,三同(函数名,参数,返回值)。
- 父类的指针或引用去调用虚函数。
虚函数的两个例外
1.协变(基类与派生类虚函数返回值类型不同)
协变,虚函数的返回值可以不同,且必须是父子类的指针或引用。
2.析构函数的重写(基类与派生类析构函数的名字不同)
问题:仅仅调用了一次父类的析构和一次从子类上切出来的父类的析构,而子类并没有调用析构,这可能导致内存泄露。
解决:让析构函数形成多态,指向父类调父类,指向子类调子类。
~Person 和~Student 底层都是一个名字~destructor()
3.再了解虚函数的重写
再重写中,只要父类加了virtual,子类不加virtual都行,因为多态调用时重写是对实现的重写。
在多态调用的时候,就是A的func和B的实现进行一个组合。
c++11的override和final
1.如何让一个类不被继承
这个方法是:把基类的构造函数放到私有里,让派生类无法创造对象。
这个方法是:给A加final,使得它变为最终类,最终类无法被继承。
如果在基类的虚函数声明中加上了final关键字,则表明****后续的派生类不能重写该函数。
final是一个关键字,它可以用来修饰类和虚函数
2.检测重写有没有毛病
派生类函数后加个override,如果没有重写虚函数就会报错。
override是编译时检查的。
重载,重写,隐藏的对比
抽象类(接口类)
抽象类:1.抽象类必须写纯虚函数,格式如上。
2.抽象类不能实例化出对象。
抽象类的派生类:必须重写纯虚函数,才能实例化出对象。
多态的原理
1.解释原理
解释:首先,要知道子类在内存中有一份父类的拷贝,子类中如果重写了父类的虚函数,那么在内存中通过地址可以找到那份拷贝,进而把它重写覆盖。
多态调用时,调用子类重写的父类的虚函数——>通过子类的虚表指针从虚表中找到子类重写的那个父类的虚函数地址,从而调用。
多态调用是运行时确定行为,是动态多态。
多态时,多了个成员就是虚表指针 注意:普通函数可不包含在内。
注意:有自己的虚函数的类才会有虚表,如果一个类只有继承下来重写了父类的虚函数而没有自己的虚函数,那这个类就没有虚函数表。
2.虚函数表位置
通过对比的方式,可以看到是存在常量区的。虚函数表是在编译时生成的。
注意:这里取自定义类型地址打印,不能强转为int,因为不是相近类型,所以得转为int*指针类型,取头四个字节就是十六进制存储的地址了。
同一个类的多个对象指向同一张虚表。如下图:
3.多继承虚表
class Base1
{
public:
virtual void func1() {cout << "Base1::func1" << endl;}
virtual void func2() {cout << "Base1::func2" << endl;}
private:
int b1;
};
class Base2
{
public:
virtual void func1() {cout << "Base2::func1" << endl;}
virtual void func2() {cout << "Base2::func2" << endl;}
private:
int b2;
};
class Derive : public Base1, public Base2
{
public:
virtual void func1() {cout << "Derive::func1" << endl;}
virtual void func3() {cout << "Derive::func3" << endl;}
private:
int d1;
};
int main()
{
Derive d;
Base1 ptr1* = &d;
Base2 ptr2* = &d;
}
理解:class Derive继承了Base1 Base2,Derive重写了Base1和Base2中的func1(),而自己也定义了一个虚函数func3()。
问题:ptr1 和 ptr2 相等吗?
答案是:不相等,看下图:
问题:Derive类自己的 虚函数 放在哪个表里?
答案是:多继承派生类的未重写的虚函数放在第一个继承基类部分的虚函数表中。
而普通的菱形继承和多继承一样。
4. 菱形虚拟继承的虚表
解释:菱形虚拟继承的内存图里,B和C都只有一份A的虚函数,没有自己的虚函数,所以只存一份虚基表的指针,A有虚函数,所以A有虚表指针。
解释:这个图就是B和C有了一份自己的虚函数,所以他俩里面也都会多存一个虚表指针。
【有道云笔记】多态
https://note.youdao.com/s/ciLJhNIj