虚函数
一、申明与定义方式
二、虚函数作用与应用
三、虚基表
1、虚函数表是与类关联的,也就是说,一个类只有一张虚函数表。(从这个方面上说,虚函数类似于类的静态函数)
2、VTable中虚函数的位置是由基类决定的,所以,哪怕你在派生类中不是按基类的顺序来重写虚函数,派生类的VTable中虚函数的存放顺序和基类的也是一样的。
3、虚函数指针VPtr是与对象关联的,每个对象都有一个虚函数指针,但是,同类的对象的虚函数指针的值是相同的。因为都指向该类的虚函数表。
4、虚函数指针VPtr的值是在调用构造函数时进行初始化的。如果该类没有构造函数,那么,默认构造函数干的唯一一件事就是初始化VPtr。所以,当你在写一个类的构造函数时,一定不要写一个空的默认构造函数。
四、C++迟绑定实现机理(编译器都是类似于此种方式实现的):
1、为每个含有虚函数的类(基类以及派生类)都创建一张虚函数表(VTable,存储于常量区),依次存放虚函数的地址。对于派生类来说,如果没有重写其基类的虚函数,那么,将会在VTable中存放基类的虚函数地址。
2、为每个含有虚函数的类的对象,创建一个指针(VPtr),指向这个类的虚函数表(所以说,同类对象的
VPtr的值是一样的,也就是说,虚函数,在这一点上,类似于类的static函数,是所有对象共有的。)
3、通过强制转换将派生类对象的地址/引用 赋给基类指针/变量(也就是向上类型转换UpCasting)
4、然后,通过基类指针/引用对象 来调用虚函数(即:polymorphic call),就会通过此时基类对象的VPtr指针在所指向虚函数表中寻址(一般是从表头地址开始,加上一定的偏移量)找到相应的函数地址,也就是之前派生类VPtr指针指向的虚函数表的函数地址。
四、虚函数继承
五、回避虚函数的默认机制
1、应用场景
基类的版本通常完成继承层次中所有类型都要做的共同任务,而派生类中定义的版本需要执行一些与派生类本身密切相关的操作;
(1)子类重写虚函数时调用基类同名函数
例如重写CDialog的OnInitDialog()时,会在首行添加一句:CDialogEx::OnInitDialog(),用来调用基类的虚函数;(https://www.cnblogs.com/zhuluqing/p/8671009.html)
(2)直接调用虚函数
double undiscounted = baseP->Quote::net_price(42) // 使用作用域运算符