文章目录
-
- 一:概念
- 二、定义和实现
- 三、析构函数的重写
- [四、 override和final关键字](#四、 override和final关键字)
- 五、重载/重写/隐藏的对比
- 六、纯虚函数和抽象类
- 七、多态的原理
-
- [5.1 虚函数表](#5.1 虚函数表)
- 动态绑定和静态绑定
一:概念
编译时多态(静态) 运行时多态(动态)
主要动态时多态:达到多种形态
给函数传不同对象完成不同的行为,达到不同效果
多态就是基类和派生类有共同的虚函数,满足三同,想实现一个功能
二、定义和实现
在类成员函数前加virtual修饰,形成虚函数
多态的实现需要满足两个条件:
- 这个功能参数必须是基类的指针或者引用
- 派生类必须堆基类的虚函数完成重写或者覆盖(返回值,函数名,参数(只看类型)都相同,函数体可以不相同)重写就是重写一下这个函数体,重写虚函数的实现
注意一下
- 派生类的virtrul可以去掉,也可以构成多态,但是不规范,选择题会埋坑
- 虚函数在类里声明加virtual关键字,在类外定义实现不需要加virtual
- 友元函数不属于成员函数,不能实现为虚函数
- 静态成员函数不能设置为虚函数,因为静态成员函数属于整个类,不属于具体的某个对象,调用时直接类::静态函数(),静态函数无需拿到this指针,就掉不到虚函数表,进而无法被写成虚函数,无法被重写
运行时跟基类没有关系,而是传谁(派生类)调用谁
只有在运行时,才知道基类的指针或者引用具体指向那个类的对象,进而再去找虚函数表,调用对应的虚函数,实现多态
你用不同的类去继承它,去重写这个虚函数。就可以调用同一个函数(函数体不同)去完成不同的功能,形成不同的形态
三、析构函数的重写
基类和派生类析构函数表面上不满足三同,因为函数名不同,但由于编译时析构函数同意编译成destroctor(),所以析构函数也可以构成重写;
为什么基类的中的析构函数建议设计成虚函数?
- 如果你不设计成虚函数,如果一个基类的指针指向一个派生类,而这个派生类里面又有资源的申请,当你去调用析构函数时候,就默认调用基类析构,会有内存泄漏的风险;
- 简单来说:父类的析构函数强力建议设置为虚函数,这样动态释放父类指针所指的子类对象时,能够达到析构的多态
- 所以设计成虚函数构成重写,指向谁调用谁,就不会出现上述情况;且析构遵循先子后父,析构完派生类会自动调用基类析构函数;
四、 override和final关键字
提示:这里可以添加技术细节
override 在编译的时候检查时候检查是否构成多态,不构成编译报错
在函数参数列表的后面加上override就可以
- 跟assert很像,区别是assert是运行时报错;
final修饰的虚函数不能被重写;
五、重载/重写/隐藏的对比
相同函数名之间函数的关系
重载:
- 首先构成重载的函数必须要在同一作用域
- 两个函数函数名相同,参数类型和个数可以不同
重写:
- 是在继承和多态之中出现的概念,两个函数的函数名,参数和返回值三者完全相同,函数体可以不同;调用时需要使用父类的指针或者引用进而构成重写
隐藏:
- 当派生类中的函数名和父类中的函数名重复了,派生类就会隐藏父类的函数,不会去调用父类的重名函数
- 可以说两个函数如果不构成重写就是隐藏
六、纯虚函数和抽象类
纯虚函数就是虚函数后面加上=0;
抽象类 特点:不能实例化出对象
实际应用中这个基类(抽象类)就会使用他的指针或者引用来指向派生类;
-
派生类如果不重写纯虚函数,那么这个派生类也是抽象类
-
所以在一定程度上如果基类是抽象类,派生类就会强制被要求重写虚函数

七、多态的原理
一个类里有虚函数,他的大小包含了这个类的成员变量和虚函数表---函数指针数组(首先他是一个数组,其次这个数组里面存放指针,而指针又指向一个个的虚函数,所以叫函数指针数组)

也就是这个ptr他可能是Person本身,也可能是切出来的Person对象;
多态函数的调用,就是你传什么对象,他就去调用那个对象的虚表,找到对应的续表函数;
动态绑定(运行时确定地址)和静态绑定(编译时确定地址)
5.1 虚函数表
·来看一段代码,了解一下虚函数表

答案是12字节
原因就是有虚函数的类,他的大小都会有一个指向虚函数表的一个指针_vptr和他的成员变量构成

关于虚函数表(简称虚表)
- 同一个类型的不同对象共享一个虚函数表
- 派生类和基类的虚函数表不是一个,只是继承下来,地址也不一样
- 一个类的不同对象共用一张虚表
虚函数和普通函数一样存在于代码段
虚函数表存在常量区
动态绑定和静态绑定
静态绑定就是编译时就只知道要调用哪个函数,对不满⾜多态条件(指针或者引⽤+调⽤虚函数)的函数就是静态绑定
动态绑定就是运行时才知道要调用那个函数,多态函数的调用就是动态绑定,运行时候才去虚表里找要调用的函数

