详解虚函数的实现过程之多重继承(3)

下面来一起探索一下多重继承时,有虚函数会怎么继承呢?
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
这里大家猜一下,SofaBed会占多少个字节呢?
首先我们是不是得猜一下它有几个虚表指针?
4* 4(4个int数据)+2*4(两个虚表指针)=24(字节)

那我们一起接下来去验证一下为什么会有两个虚表指针呢?冲冲冲!!!

是不是感觉很神,对吧?两个虚表指针,它怎么排兵布阵的呀?这得接下来一起看看喽:

在这里插入图片描述

从上面表格可以看出它所继承的父类中各自有一个指针,查了一下指针指向的地方,分别是0x426198与0x42501C,接下来我们去看看这两个地方所存在的数据:
在这里插入图片描述
啊这,这两个虚表里面保存了子类的虚函数和父类的虚函数,父类的虚函数都是在子类中没有实现的。编译器将CSofaBed的虚函数制作了两份,为什么会有两份呢?那我们是不是应该去看看构造函数呢?对吧,接下来往下冲:

在这里插入图片描述
它首先调用了父类CSofa的构造函数(地址401205处)。在调用另一个父类CBed时,并不是直接将对象的首地址作为this指针传递,而是向后调整了父类CSofa的长度(this+8)(ecx为什么加8呢?因为虚表指针占4字节,m_nColor占四字节,所以就加8),以调整后的地址值作为this指针,最后再调用CBed(地址40120A~地址401214)的构造函数。。

由于有了两个父类,因此子类在继承时也将他们的虚表指针一起继承过来,也就有了两个虚表指针。可见,在多重继承中,子类虚表指针的个数取决于所继承父类的个数,有几个父类便会出现几个虚表指针。(虚基类除外,这个另讨论)

当虚表指针在将子类对象转换成父类指针使用时,每个虚表对应着一个父类,使用方法也就有点不太一样,我们一起看来看看吧:

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

当子类对象转换成不同的父类指针时,调整的位置也就不一样,当在转换成CSofa指针时,会直接取对象首地址,当在转换成CBed指针时,会调整首地址(地址40F747处)并跳过第一个父类所占用的空间(占用8字节,所以+8)。

下面我们来看看它的析构函数是怎么样的:

在这里插入图片描述
在这里插入图片描述
由于具有多个父类(多个同时继承的父类),因此子类中产生了多个虚表指针。
在对父类进行析构时,需要设置this指针,用于调用父类的虚构函数。由于具有多个父类,当在析构的过程中调用各个父类的析构函数时,传递的首地址将有所不同,编译器会根据每个父类在对象中所占用的空间位置,对应地传入各个父类的首地址作为this指针。

总结如下:
单继承类:
a.在类对象占用的内存空间中,只保存一份虚表指针
b.由于只有一个虚表指针,对应的也只有一个虚表
c.虚表中各项保存了类中各虚函数的首地址
d.构造时先构造父类,再构造父类,并且只调用一次父类构造函数
e.析构时先析构自身,再析构父类,并且只调用一次父类析构函数

多继承类:
a.在类对象所占用的内存空间中,根据继承父类的个数保存对应的虚表指针
b.根据所保存的虚表指针的个数,对应产生相应个数的虚表
c.转换父类构造函数,需要调整到对象的首地址
d.构造时需要调用多个父类构造函数
e.构造时先构造继承列表中第一个父类,然后依次调用最后一个继承的父类构造函数
f.构造时先构造继承列表中的第一个父类,然后依次调用到最后一个继承的父类构造函数
g.析构时先析构自身,然后以构造函数相反的顺序调用所有父类的析构函数。
h.当对象作为成员时,整个类对象的内存结构和多重继承很相似。当类中无虚函数时,整个类对象的内存结构和多重继承完全一样,可酌情还原;当父类或成员对象存在虚函数时,通过观察虚表指针的位置和构造函数,析构函数中填写虚表指针的数目以目标地址,来还原继承或成员关系

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

寻梦&之璐

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

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

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

打赏作者

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

抵扣说明:

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

余额充值