c++之多态
2020-03-12 本文已影响0人
全村的卡密
父类指针、子类指针
-
父类指针可以指向子类的对象
image.png
多态
- 同一操作作用于不同对象,可以有不同的解释,产生不同的执行结果。
- 默认情况下,c++只会根据指针类型调用对应的函数,不存在多态。
Animal *p = new Cat();
//并不会调用 cat 的函数,而是调用animal的函数。
c++通过虚函数实现多态
- virtual声明虚函数
- 父类如果写了虚函数,那么子类对应函数也是虚函数,不需要写virtual.
class Animal{
public:
virtual void run(){
cout<<"animal run"<<endl;
}
class Cat{
void run(){
cout<<"cat run"<<endl;
}
}
重写(override)
- 子类函数对父类函数的覆写。
多态的要素
- 子类重写父类的成员函数(override)
- 父类指针指向子类对象
- 利用父类指针调用(重写的)成员函数
虚函数与普通函数的汇编区别
![](https://img.haomeiwen.com/i4283026/af4b35284e1465d7.png)
speak()是普通函数,run()是虚函数。
虚函数原理
使用sizeof计算虚函数占用内存大小,发现它比普通函数大了4个字节(x86),是因为其中有一个指向虚表的指针。
虚表
-
虚表存储着最终需要调用的虚函数指针
image.png
![](https://img.haomeiwen.com/i4283026/edddb46492b37fca.png)
结合上表,就能理解汇编代码
![](https://img.haomeiwen.com/i4283026/3040ac0bf8172348.png)
![](https://img.haomeiwen.com/i4283026/6d776789429fd4d3.png)
![](https://img.haomeiwen.com/i4283026/f54c7b1297bab4fa.png)
调用父类成员函数
父类::函数名
animal::speak();
虚析构函数
- 如果存在父类指针指向子类对象的情况,应该将析构函数声明为虚函数(虚析构函数)
- delete父类指针时,才会调用子类的析构函数,保证析构的完整性
纯虚函数
- 没有函数体且定义为0的的虚函数,用来定义接口规范
virtual void run() = 0;
抽象类
- 含有纯虚函数的类,不可以实例化
- 如果父类是抽象类,而子类没有完全重写纯虚函数,子类依然是抽象类
多继承
- c++允许一个子类有多个父类,但是不建议使用,增加复杂性。
- 如果子类继承的多个父类有虚函数,则子类会有多个虚表。
虚继承
虚继承能解决菱形继承的问题(变量冗余)
![](https://img.haomeiwen.com/i4283026/21e66a4d7e6aefb7.png)
![](https://img.haomeiwen.com/i4283026/fc4553d79080b01b.png)
![](https://img.haomeiwen.com/i4283026/7d3f72e3015acf95.png)