详解虚函数的实现过程之菱形继承(5)

大家看到标题,会不会菱形继承的虚表会不会是重复的呢?祖父类的虚表会不会在子类会不会是两份相同呢?那么我们一起来探索一下吧,冲冲冲!!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

首先我们来分析一下:
它一共定义了四个类,分别为CFurniture,CSofa,CBed和CSofaBed。CFurniture为祖父类,从CFurniture类中派生了两个子类:CSofa与CBed,它们在继承时使用了virtual的方式,即虚继承。

接下来我们来看看CSofaBed的对象的内存结构图
在这里插入图片描述
那么这些数据都有什么含义呢?如下所示:
在这里插入图片描述

看了一下,大概能看懂,但是还有一个模糊不清的数据无法理解,就像CSofaBed_vt(new)和vt_offset,他们又代表什么东西呢?唉,只能去探索汇编代码,继续冲冲冲!!!

在这里插入图片描述
在这里插入图片描述
在这里解释一下地址40F732~40F742之间汇编代码的作用:

ebp-24h是对象的向后偏移四个字节的地址,因为ebp-28h是this指针,也就是对象的首地址,this值即内存图中的12FF58,所以[ebp-24h]也就是对象的第二个字节的数据,其实说白了它还是个地址,也就是12-13内存图中的第二行数据 425050,即[ebp-24h]的值是425050,然后放入ecx中,ecx+4也就是这个地址向后偏移 4个字节,即425054,然后[ecx+4]的值即为1C,这个值就是父类虚表指针相对于vt_offset的偏移,然后把这个值放入edx,作为一个偏移值,ebp-24h+edx 意思就是相对于第二个字节的偏移为1C的地址,[ebp-24h+edx]不就是这个地址的值了吗?也就是祖父类的首地址,即祖父类的虚表指针的地址

上面分析了一下汇编代码,分析出了vt_offset所指向的内存地址中保存的数据为偏移数据。如下图,图中每个vt_offset对应的数据有两项:第一项是-4,即vt_offset所属类对应的虚表指针相对于vt_offset的偏移值;第二项保存的是父类虚表指针相对于vt_offset的偏移值(上面已分析结束,至于第一项的话,大家看汇编代码都能看出)

在这里插入图片描述
根据上面我们找出的vt_offset是地址12FF5C,向下偏移1C的话,1C是多少个字节?刚开始我一直搞成12个字节?!!!!!我都搞不懂那个1被我想哪去了?!!!1C也就是 16+12=28个字节,也就是向下偏移7行,即到地址12FF78处,它的值为42501C,这也就是父类虚指针的地址。当然也可以用第二个来算,因为它俩的父类都是同一个,所以算出来的地址肯定也是42501C(快速算一下:也就是425044的地址是12FF68,然后向下偏移10h(16个字节)个字节,也就是4行,即12FF78处,值为42501C)

根据前面所述,这里有三个虚表指针:
0x425034(用0x12FF5C -0x4=0x12FF58,根据上面内存图此处地址的值为0x425034),0x425028(从汇编代码地址0x40F752分析得出)(至于0x12FF68如何得来,需要去分析汇编代码,用0x12FF68 -0x4=0x12FF64,根据上面内存图此处地址的值为0x425028),
0x42501C(已算出是祖父类起始地址)

所以总结如下:

vt_offset是一个地址,这个地址所指向的地方存在了两个偏移值,第一个值是当前类对应的虚表指针相对于vt_offset的偏移值,第二个值是父类对应的虚表指针相对于vt_offset的偏移值,每个虚继承类都有一个相应的vt_offset,可找到父类的虚表指针,也可找到自身类的虚表指针。

在这里插入图片描述
这三个虚表指针指向的虚表包含了子类CSofaBed含有的虚函数有了这些记录就可以随心所欲地将虚表指针转换成任意的父类指针。
在利用父类指针父类指针访问虚函数时,只能调用子类与父类共有的虚函数,子类继承自其它父类的虚函数是无法调用的,虚表中也没有相关记录。当子类的父类存在多个父类时,会在12-15所显示的表格中依次记录它们的偏移。

虚函数系列:
详解虚函数的实现过程之初探虚表(1)
详解虚函数的实现过程之单继承(2)
详解虚函数的实现过程之多重继承(3)
详解虚函数的实现过程之虚基类(4)
详解虚函数的实现过程之菱形继承(5)

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寻梦&之璐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值