目录:
1.多态实现原理(再剖析)
2.析构函数加virtual
3.C++11新增两个关键字 override 和 final
4.重载、覆盖(重写)、隐藏的对比
5.抽象类
1.多态实现原理(再剖析)
实现出多态的效果,我们要先判断是否符合多态的条件
1.虚函数的重写
2.父类指针或引用去调用
---------------------------------------------------------------------------------------------------------------------------------
一个实现出了多态,一个没有实现出多态
那么C++是如何考量这两份代码的调用的呢????
我们得先知道,虚函数被编译完了,虚函数是存在哪的???
很多人会误以为虚函数是存在虚表,这里要注意的是任何函数被编译好了之后都是指令,被放到公共的代码段当中。虚表当中放的是虚函数的地址
虚函数表 --- 简称虚表
本质函数指针数组
我们看看构成多态的调用情况是怎么样的
Func的参数是引用,我父类对象的调用就可以找到父类对象的虚表
我是子类对象的引用就可以通过切割、切片,变成子类当中父类那一部分的引用,找到子类当中的虚表。
--------------------------------------------------------------------------------------------------------------------------------
我们来看看要是破坏了虚函数重写会是什么情况
我们先把父类的虚函数
我们破坏子类的虚函数
2.析构函数加virtual
析构函数为什么要求加virtual呢???
这里的子类和父类析构函数为什么构成了重写呢???
子类和父类都没有返回值,参数也相同,可函数名不相同啊,为什么也会构成虚函数的重写呢??
原因是因为这里的析构函数名被编译器统一处理成了destructor
可编译器为什么要将析构函数名统一处理成destructor
哪怕这样子我们析构函数不加virtual都是没有问题的
我们换一种情况来看看
我们这里的析构函数不是虚函数,所以这里就是一个普通调用,普通调用就是在编译就决定了析构函数的地址,在编译的时候这里call 的一个函数 就是Person当中的虚函数(按ptr1的类型去调)但是这里我们想调用的并不是Person的析构函数,我们想调用的是Student的析构函数
所以为了解决上面的这种情况,我们为了能够调用到Student的析构函数,千方百计的为析构函数加virtual
子类析构函数重写父类析构函数,这里才能正确调用
指向父类的调用父类的析构函数
指向子类的调用子类的析构函数
3.C++11新增两个关键字 override 和 final
1.final:修饰虚函数,表示该虚函数不能再被重写
在这个虚函数后面加final
override : 检查派生类虚函数是否重写了基类的某个虚函数,如果没有重写编译报错
4.重载、覆盖(重写)、隐藏的对比
5.抽象类
概念 : 在虚函数后面写上=0,则这个函数为纯虚函数,包函数纯虚函数的类叫抽象类(也叫接口类),抽象类不能实例化对象,派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象
间接强制你去完成纯虚函数的重写 ,override是检查是否完成重写