200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 详解虚函数的实现过程之多重继承(3)

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

时间:2024-06-27 01:04:24

相关推荐

详解虚函数的实现过程之多重继承(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)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。