概念
在C++中,多态主要通过以下两种方式实现:
- 编译时多态:也称为静态多态,主要是通过函数重载(Overloading)和运算符重载(Operator Overloading)来实现。
- 函数重载:允许在同一个作用域内定义多个同名但参数列表不同的函数。
- 运算符重载:允许为已有的运算符提供新的语义,使其可以用于用户自定义类型的对象上。
- 运行时多态:也称为动态多态,是通过继承和虚函数(Virtual Functions)来实现的。
- 虚函数:在基类中声明为的成员函数可以在派生类中被重写(Override)。当通过指向基类的指针或引用调用虚函数时,实际执行的是派生类中重写的版本。
- 纯虚函数与抽象类:如果一个虚函数在基类中没有提供实现,则它被称为纯虚函数(pure virtual function),通常形式为 。包含至少一个纯虚函数的类被称为抽象类(Abstract Class),不能直接实例化。
原理剖析
静态多态:
为了识别不同的函数。编译器和链接器会根据函数名,函数参数类型,所在类和命令空间等信息修饰函数。修饰后的结果也就是函数签名。编译器和链接器所做的操作都是在函数运行前,所以这是静态多态
动态多态
如果类中含有虚函数,这个类就会生成一个虚函数表(vtbl),每一个类实例都会有一个虚函数指针(vptr)。虚函数表(相当于虚函数数组)里按序排列着虚函数,子类继承父类会复制父类的虚函数表,子类如果改写父类的函数,则在虚函数表里面替换对应的父类的虚函数。动态多态运行时相当于这段代码(*p->vptr[n])(p)
,p是指向类实例的指针。具体如下
多种继承的内存情况
多重继承
例如class Derive : public Base1, public Base2, public Base3
,则子类有三个虚函数指针(vptr),指向三个不同的虚表。
重复继承
即两个父类都继承自同一个类。则与多重继承相同。只不过多了一份重复的内存,虚函数指针还是两个
钻石继承
为了解决上述多了一份重复内存的问题,引入了钻石继承,即
class Base1 : virtual public Base0
class Base2 : virtual public Base0
class Derive : public Base1, public Base 2
结果:还是含有两个虚函数指针,最上层父类的数据在钻石底层的类中只有一份了
参考:
https://coolshell.cn/articles/12176.html
候捷面向对象课程