多态:顾名思义就是相同的事情经过不同的对象来做得到不同的结果
例如买票问题,
成人买票时点击购买就会出现全票价格
而学生买票就会出现的是半价价格
相同的买票行为,不同的对象来做,产生了不同的结果,这种行为就是多态行为。
实现多态必须满足的条件:
1.前提:继承
2.虚函数
3.调用虚函数的类型必须是指针或者引用
4.虚函数需要被重写
5.一般都是父类的指针或引用调用虚函数
虚函数重写:
1.函数名,参数列表,返回值和父类虚函数完全相同
2.协变:返回值可以不是同一个类型,但是必须是由继承关系的指针或者引用
多态执行结果 看对象
非多态 看类型
一般把析构函数定义成虚函数,产生多态行为,保证资源被正确释放
Override关键字:强制重写,检查函数是否写了父类的某一个虚函数
体现接口(返回值,函数名,参数列表)继承,不继承实现
Final关键字:
1.修饰虚函数:此虚函数不能被子类重写
2.修饰类:类名final–》此类不能被继承
抽象类:包含纯虚函数
抽象类不能实例化
+++类似于间接的强制重写
函数重载:
1.两个函数在同一作用域
2.函数名相同/参数不相同
函数重写(覆盖):
1.两个函数分别在基类和派生类作用域
2.函数名/参数/返回值都必须相同(协变除外)
3.两个函数必须是虚函数
函数重定义(隐藏)
1.两个函数分别在基类和派生类的作用域
2.函数名相同
3.两个基类和派生类的同名函数不构成重写就是重定义
子类会继承父类的虚表
子类重写的虚函数,对应的重写的虚函数地址会覆盖掉虚表中对应的虚表指针
虚表没有存放在对象中
虚表存放在代码段
多态场景:
1.从对象中获取虚表指针
2.通过虚表指针找到虚表
3.在虚表中找到虚函数地址
4.执行虚函数指令
编译时多态:前期绑定 函数重载,模板
运行时多态:后期绑定 函数重写
虚表指针
每个实现多态的对象都会有一个虚表指针,有几个父类就会有几个虚表指针,指向不同的虚表,这些虚表保存在对象的开始依次占四个字节(64位为8字节)的位置
实行多态时,先经过对象中的虚表指针找到虚表,
然后在虚表中寻找虚函数进行函数调用,
不同的对象会调用各自虚表中的虚函数,
如果父类虚函数被重写那么子类中的虚函数表中会重写(覆盖)这个名字函数的虚函数指针从而使得每次调用不同的对象时,产生不同的结果