概念
多种形态
静态的多态:函数重载,看起来调用同一个函数有不同行为
动态的多态:一个父类对象的引用或指针去调用同一个函数传递不同的对象会调用不同的函数
重写及多态的构成条件
子类中满足三同(函数名,参数,返回值)的虚函数叫做重写(覆盖)
本质:不同人做同一件事得到不同的结果
多态的构成条件:
1,必须是通过基类的指针或引用调用虚函数
2,被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写
构成多态:传的哪个类的对象调用的就是这个类型的虚函数-----跟对象有关
不构成多态:调用的就是p类型的函数-----跟类型有关
重写要求返回值相同有一个例外:协变-----要求返回值是父子关系的指针或引用
析构函数的多态
析构函数是虚函数构成重写(都被处理成了destructor)
普通对象,析构函数是否是虚函数,是否完成了重写都正确调用了
动态申请的对象,如果类型是父类指针,那么需要析构函数是虚函数
例子1:
person* p1=new person
person* p2=new student
符合多态,和对象有关,如果没写虚函数,对象p1,p2都只调用person类的析构函数,加了virtual才能析构子类的student的析构
例子2:
person* p1=new person
student* p2=new student
不构成多态,跟类型有关,分别调用person和student的析构
例外:虚函数的重写允许两个都是虚函数或父类是虚函数
final和override及其知识对比
final修饰虚函数,限制它不能被子类中的虚函数重写,不希望被继承可以加final
override检查是否重写,没有重写就会报错
抽象类
在虚函数的后面写上=0,则这个函数叫做纯虚函数。包含纯虚函数的类叫做抽象类(也叫抽口类)。抽象类不能实例化出对象,派生类继承后也不能实例化出对象
纯虚函数的类本质上强制子类去完成虚函数重写
虚函数表
根据调试看看
可以看出有了虚函数,对象中就多了一个虚函数表指针,简称虚表指针
同类型的对象,虚表指针是相同的,指向同一张虚表
虚表是什么阶段初始化的?虚函数存在哪里?
虚表实际上是在构造函数初始化列表阶段进行初始化的,注意虚表当中存的是虚函数的地址不是虚函数,虚函数和普通函数一样,都是存在代码段的,只是他的地址又存到了虚表当中。另外,对象中存的不是虚表而是指向虚表的指针。虚表是存在代码段的,本质上从类型角度:函数指针数组
不是多态,编译时确定地址
符合多态条件,才会到虚函数表中去找,再调用