多重继承时的虚函数表

本文详细解析了一个C++示例代码,重点介绍了多重继承中的内存布局及虚函数表的工作原理。通过具体实例解释了虚函数如何在不同基类间正确调用,并分析了虚函数表指针对内存对齐的影响。

分析以下一段代码(vs2010编译)

 1 #include<iostream>
 2 using namespace std;
 3 class ba
 4 {
 5 public:
 6     double dd;
 7 };
 8 class bas
 9 {
10 public:
11     double d;
12 };
13 
14 class base1
15 {
16     char u;
17 public:
18     virtual void h(){cout<<"base1"<<endl;}
19     virtual void f(){cout<<"base1"<<endl;}
20 };
21 class base2
22 {
23 public:
24     virtual void k(){cout<<"base2"<<endl;}
25     virtual void g(){cout<<"base2"<<endl;}
26     virtual void f(){cout<<"base2"<<endl;}
27     
28 };
29 
30 class base3
31 {
32 public:
33     virtual void e(){cout<<"base3"<<endl;}
34     virtual void f(){cout<<"base3"<<endl;}
35     virtual void g(){cout<<"base3"<<endl;}
36 };
37 class deri:public ba,public base1,public base2,public bas,public base3
38 {
39     char ch;
40 public:
41     void g(){}
42     virtual void ff(){cout<<"deri ff"<<endl;}
43     void f(){cout<<"deri f"<<endl;}
44     void e(){}
45 };
46 int main()
47 {
48     deri dd;    
49     base1* pb1=&dd; 
50     base2* pb2=&dd;
51     printf("%x\n",*((int*)pb1));
52     cout<<pb1<<endl;
53     cout<<pb2<<endl;
54     return 0;  
55 } 
View Code

deri类的内存分布是这样的:

也就是说,含有虚函数的父类排列在没有虚函数的父类之前。在这两种类的内部,父类的分布是按继承时的声明次序排列的,每个父类的成分都非常完整。这个deri类有三个虚函数表指针,同时注意虚函数指针所带来的内存对齐。

对于每一张虚函数表,虚函数在表中的排列次序是按照类中的声明次序来的。deri类自己新增的虚函数会添加到第一张虚函数表的末尾。

对于至少两个父类均有的虚函数(f(),g()),第一个拥有该虚函数的父类的虚表中填入了函数的地址(&deri::f,&deri::g),之后的表都只是记录一个偏移值,即自身指针减去这个偏移值之后(this-=8  this-=12  this-=4),就可以得到第一个拥有该虚函数的父类的起始地址,然后可以调用相应的虚函数。

最后四行是指明了deri类中虚函数的地址分别所在的表的偏移。

 

转载于:https://www.cnblogs.com/vaecn/p/5362645.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值