C++ 虚函数表与多态 —— 继承的虚函数表 & 内存布局

1. 使用继承的虚函数表:

如果不涉及多重继承,每个类只有1个虚函数表,当子类继承父类后,子类可以自己改写和新增虚函数,如下图所示:

C++ 虚函数表与多态 —— 继承的虚函数表 & 内存布局

 

 

子类重写 func_1 后,子函数的 func_1 将会有新的逻辑,不会干扰到父类;

子类新增行的 func_4 方法后,父类无法访问到该方法。

 

如下代码:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class Father
 5 {
 6 public:
 7     virtual void func_1() { cout << "Father::func_1"; }
 8     virtual void func_2() { cout << "Father::func_2"; }
 9     virtual void func_3() { cout << "Father::func_3"; }
10 public:
11     int x = 666;
12     int y = 999;
13 };
14 
15 class Son : public Father
16 {
17 public:
18     void func_1() { cout << "Son::func_1   "; }                //重写了虚函数
19     virtual void func_4() { cout << "Son::func_4   "; }        //子类对象新写的虚函数 func_4
20 };
21 
22 typedef void(*func_t)(void);
23 
24 int main(void)
25 {
26     Father father;
27     cout << "father 对象地址:" << (int*)&father << endl;
28     int* vptr_f = (int*)*(int*)&father;                                //虚表指针
29 
30     for (int i = 0; i < 3; i++)                //这里如果想循环4次往下访问,不会访问到子类的 func_4 ,会访问到非法内存
31     {
32         cout << "调用第" << i + 1 << "个虚函数:";
33         ((func_t) * (vptr_f + i))();
34         cout << "地址为:" << *(int*)(vptr_f + i) << endl;
35     }
36 
37     cout << "==============================================" << endl;
38 
39     Son son;
40     cout << "son 对象地址:" << (int*)&son << endl;
41     int* vptr_s = (int*)*(int*)&son;                                //虚表指针
42 
43     for (int i = 0; i < 4; i++)
44     {
45         cout << "调用第" << i + 1 << "个虚函数:";
46         ((func_t) * (vptr_s + i))();
47         cout << "地址为:" << *(int*)(vptr_s + i) << endl;            //打印每个虚函数的地址
48     }
49 
50     for (int i = 0; i < 2; i++)
51     {
52         cout << *(int*)((int)&son + 4 + i * 4) << endl;
53     }
54     cout << "sizof(son)==" << sizeof(son) << endl;
55 }

 

 

运行结果:

C++ 虚函数表与多态 —— 继承的虚函数表 & 内存布局

 

 

子类的虚函数表生成:

 看上图可知,子类对象的 func_1() 地址与父类的 func_1() 地址便可知,重写的虚函数并不是把父类的同名函数覆盖改写,而是在新内存新写。

子类对象是先将父类虚函数表的成员地址全部复制下来,如果子类重写了父类的某个虚函数,便将被重写虚函数的指针,改为新虚函数的指针(指针替换)。

如果子类增加了新的虚函数,那么就会把这个虚函数的地址添加到虚函数表的表尾部。

 

注意:如果仔细观察我们可以发现,上图中按顺序走的虚函数所存放的地址不同,Father的3个func函数地址不是线性排序。

 

 

 

 

 

 

 

 

 

 

===========================================================================================================

原文链接: https://www.cnblogs.com/CooCoChoco/p/12556468.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++ 虚函数表与多态 —— 继承的虚函数表 & 内存布局

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/337345

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午11:06
下一篇 2023年3月1日 下午11:06

相关推荐