C++ 多态
1、虚函数
类的成员函数前面加上 virtual 关键字,这个成员函数称为虚函数。
2、虚函数重写
当在子类定义了一个与父类完全相同的虚函数时,则称子类的这个函数重写了父类的虚函数。
3、多态
- 静态多态:利用函数重载,编译时确定。
- 动态多态:利用类继承,虚函数机制实现。运行时确定。
4、构造函数不能定义成虚函数
在构造一个对象的时候,必须知道对象的实际类型,而虚函数时在运行时才能够确定实际
类型,而在构造一个对象的时候,由于对象还未构造成功,编译器无法知道对象的实际类
型,是该类本身,还是该类的派生类。
虚函数的执行依赖于虚函数表,而虚函数表是在构造函数中进行初始化工作的,即初始化
vptr,让它指向正确的虚函数表。构造函数期间,虚函数表还没有初始化完毕,将无法进
行。
5、构造函数与析构函数内不要调用虚函数
在基类构造的时候,此时的虚函数还是非虚的。不会走到派生类当中,此时采用的静态绑定,
即编译时绑定。但是当构造一个子类的时候,先调用父类的构造函数,而父类的构造函数中调
用了虚函数,但是子类此时并没有将虚表初始化,所以这个过程是非常危险的。
在进行析构的时候,先调用子类的析构函数,析构掉对象中子类部分,接着调用父类的析构函
数,如果父类的析构函数中调用了虚函数,可能会导致其调用了已经析构了的子类里的虚函数,
这样的话也是非常危险的。
6、重载、重写、重定义
重载:在相同的作用域,函数名相同,参数不同,返回值可以不同。
重写:不在同一作用域(分别在基类与派生类),函数名相同、参数相同、返回值相同,基类
函数必须有 virtual 关键字。
重定义:不在同一作用域(分别基类与派生类),函数名相同。
7、纯虚函数
派生类必须重写该虚函数,否则无法实例化对象。
8.菱形继承与菱形虚继承
菱形继承构建多态以后,子类会有两张虚表,这两张虚表中都包含两个基类所共同继承的一个基类
的数据。并且子类的虚函数如果进行了重写,会同时改变两张表上的,并且子类自己的虚函数会放
置逻辑上第一个继承的基类的虚表当中去。
如果是菱形虚继承构建多态。那么一般情况下子类当中有三张虚表,分别是所继承的连个基类的自
己的虚表,如果两个基类没有自己的虚函数,或者是重写父类的虚函数,那么该基类没有虚表。而
它们共同继承的基类的虚表在子类的虚表当中。而两个基类中存储着该虚表的偏移量。
欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!