多态:顾名思义,就是多种形态,在继承体系中,子类需要有自己的表现形态
实现多态的前提:
1、实现继承
2、是虚函数
3、调用的函数必须是引用或指针
虚函数的覆写
函数为虚函数,子类有相同的函数,和父类的函数名相同,参数也相同,返回值类型也相同(接口完全相同)。例外:协变:返回值类型可以是继承关系
三者区别:
函数重载:同一个作用域下,函数名相同,参数不同
函数隐藏:继承体系中,子类和父类的函数名相同
函数覆写:继承体系中,子类和父类的接口完全相同
在继承中,析构函数尽量都写成虚的,可以和子类构成多态
继承和多态区别
多态体现的是接口继承,把外观继承下来,具体功能自己实现,普通继承体现实现继承,直接拿着用
纯虚函数:
virtual关键字,然后还得等于0;并不是为了实现,而是给大家提供一个统一的接口,父类的代码用不上
抽象类(体现接口继承)
有纯虚函数的类就是抽象类,抽象类不可以实例化,因为函数都没有定义
final:
不能被重写,体现实现继承
override
在子类,这个函数必须重写一个父类的函数,体现接口继承
多态在底层是如何实现的?
虚表指针:存放在对象模型的头部,是一个二级指针。类型为:虚函数**
实际上就是_vfptr
虚表:是一个数组,每个数组元素是一个虚函数指针,所以它是一个函数指针数组
如何知道虚表位于哪里?
分别定义4个区域的变量,取地址,看虚表地址与哪个最近,事实上,虚表存在于代码段(vs中)
如果继承了n个父类,那么虚表也是n个,子类新增的虚函数存放在第一个直接父类虚表末尾(按声明顺序存放)
关于多态中如何调用的问题?
没有覆写的话,调用的就是父类的,覆写了的话就改为自己的地址,自定义的也是自己的地址。