【cpp进阶-01】谈谈多态问题
前言
继承、封装、多态是面向对象的三大特性。
本文主要介绍一些多态的细节来深入cpp。
静态多态
重载
重载函数
-
定义:
在作用域范围内有多个名称相同但参数签名不同的函数
-
注意:
(1)返回值不能作为重载的判断依据
(2)派生类不能重载基类的同名函数,会遮蔽掉基类的函数
-
底层实现:
cpp在编译时会根据命名空间、类、参数类型进行名字编码,形成新的函数名,重载的不同函数便有不同的函数地址入口。
重载运算符
将operator 运算符名称
看作函数进行重载
-
成员函数的重载 与 全局函数的重载 选择
+,-,*,/,==,!=
建议全局重载+=,-=,*=,/=
建议成员重载 -
原因:转换构造函数
Complex{ ... friend Complex operator+(const Complex &c1, const Complex &c2); ... } //友元+全局函数 Complex operator+(const Complex &c1, const Complex &c2){ return Complex(c1.m_real + c2.m_real, c1.m_imag + c2.m_imag); } Complex c = Complex(1.0) + 2.0; //true: const&:允许引用右值;自动类型转换。
模板与泛型
参数推断
定义时不指明参数类型,调用时通过实参进行推断。
关键字:template<typename T>
动态多态
继承与虚函数
-
为什么 基类的指针指向派生类对象,成员变量是派生类的,而成员函数是基类的?
根据cpp对象的内存模型解释:
(1)成员变量:对象独有,与对象(派生类对象)绑定;
(2)成员函数:类共享,预处理时根据类型,参数列表等重新命名函数,与类(基类)绑定;
-
为什么 虚函数可以解决上述问题?
每个对象内存中存在一个虚函数表的指针,调用函数时通过派生类对象的虚函数指针调用正确的函数。
-
为什么 构造函数不能是虚函数?
(1)构造函数无法继承,虚函数没有意义。
(2)构造函数用于初始化,创建对象未完成,虚函数表指针尚未初始化,无法查询虚函数表调用正确的构造函数。
-
为什么 析构函数使用虚函数?
(1)若派生类在基类的基础上多生产了指针,使用了空间,不使用虚析构函数会导致部分空间不能被释放,内存泄漏
-
解释一下虚函数表的内存模型

(1)每一种类型独有一种虚函数表
(2)如果派生类的同名虚函数遮蔽了基类的虚函数,将表中的函数进行替换
(3)对象创建时在开头生成虚表指针指向类型的虚函数表
-
纯虚函数 和 抽象类
(1)
virtual = 0
表示纯虚函数(2)抽象类无法实例化