15多重继承虚继承的内存布局Word格式.docx

上传人:b****4 文档编号:16392846 上传时间:2022-11-23 格式:DOCX 页数:17 大小:340.22KB
下载 相关 举报
15多重继承虚继承的内存布局Word格式.docx_第1页
第1页 / 共17页
15多重继承虚继承的内存布局Word格式.docx_第2页
第2页 / 共17页
15多重继承虚继承的内存布局Word格式.docx_第3页
第3页 / 共17页
15多重继承虚继承的内存布局Word格式.docx_第4页
第4页 / 共17页
15多重继承虚继承的内存布局Word格式.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

15多重继承虚继承的内存布局Word格式.docx

《15多重继承虚继承的内存布局Word格式.docx》由会员分享,可在线阅读,更多相关《15多重继承虚继承的内存布局Word格式.docx(17页珍藏版)》请在冰豆网上搜索。

15多重继承虚继承的内存布局Word格式.docx

3)派生类新增的数据成员

其中,派生类的虚表,是在基类的虚表基础之上所作的修改,有可能是:

1)对基类中虚函数地址的覆盖

2)派生类中新增的虚函数地址

1)只要有虚函数,就有虚表产生。

2)虚表中条目的个数,是本类中虚函数的个数

3)虚表中各条目的顺序,与类中声明(定义)的虚函数顺序一致

 

1.3多重继承,无虚函数的情况

多重继承、无虚函数的情况是:

这里与1.1单继承,无虚函数的情况的差别是——可能存在多个基类。

这里基类数据成员的排放,是按照继承的数据依次进行的。

1.4多重继承,有虚函数的情况

多重继承,有虚函数的情况是:

1)基类的虚表指针

3)基类的虚表指针

4)基类的数据成员

5)派生类新增的数据成员

这里与1.2单继承,有虚函数的情况的差别是——虚表

这里说基类的虚表指针,其实是不太恰当的,因为它们实际上是派生类虚表的一部分。

也就说,派生类的虚表是由多个基类的虚表所构成的。

不存在一个单一的派生类的虚表。

派生类的虚表条目是在各基类的虚表基础之上修改所得,可能包括:

1)对基类中虚函数的覆盖,会更新各基类虚表中的条目

2)派生类中新增的虚函数地址,会追加到第一个继承的基类的虚表中

至此,上面

是从单继承/多重继承,无/有虚函数的角度进行的梳理。

下面将以菱形继承为主线,来进行梳理。

(菱形继承中可能出现二义性,会逐步的引入虚继承,虚基类的概念)

菱形继承(diamond-inheritance)

1.5菱形继承,无虚函数的情况

ClassA{};

ClassB:

publicA{};

ClassC:

ClassD:

publicB,publicC{};

菱形继承,无虚函数的情况是:

1)基类B的数据成员

a)基类A的数据成员

b)派生类B新增的数据成员

2)基类C的数据成员

b)派生类C新增的数据成员

3)派生类D新增的数据成员

这里仍然是没有太大的变化,按照基类、派生类的顺序安放数据成员。

1.6菱形继承,有虚函数的情况

菱形继承,有虚函数的情况:

1)基类B的虚表指针

a)基类A的虚函数(未被覆盖的部分)

b)基类B的虚函数(覆盖A的部分,新增的部分)

c)派生类D的虚函数(新增的部分)

2)基类B的数据成员

3)基类C的虚表指针

a)基类A的函数(未被覆盖的部分)

b)基类C的虚函数(覆盖A的部分,新增的部分

4)基类C的数据成员

5)派生类D新增的数据成员

仍然要说一点,这里说基类的虚表指针,其实是不太合适的,它们是派生类的虚表的一部分,是派生类在基类的虚表基础之上所做修改而来的:

1)如果派生类中的虚函数与基类中的形成覆盖,则派生类会对基类的虚表中相应条目做覆盖处理

2)派生类中新增的虚函数地址,追加至第一个继承的基类虚表中。

1.7菱形继承,无虚函数,为虚继承的情况

在上面的

中,最基类A,在内存空间中有多份拷贝。

利用虚继承可以解决,此时最基类A成为虚基类。

所以,菱形继承,无虚函数,为虚继承的情况,也就是菱形继承,无虚函数,有虚基类的情况。

虚继承的引入,使得虚基类在内存中仅存一份拷贝,同时带来的影响还有内存空间布局的变化。

大概有:

1)虚基类的数据成员在内存中的位置

2)偏移表

偏移表的存在,是因为——虚基类的单份存在,而虚基类A又被B,C所共享,所以对B,C而言,它们就各自需要确定A的所在位置。

偏移表就是用于该问题。

偏移表的数目,就是直接继承自虚基类的派生类的数目。

现在来一一测试。

在看到这些信息后,我们猜测其内存空间的布局:

1)B的偏移表,在ecx处

2)B的数据成员,在ecx+4处

3)C的偏移表,在ecx+8处

4)C的数据成员,在ecx+0C处

5)D的数据成员,在ecx+10处

6)A的数据成员,在ecx+14处

下面先对偏移表进行跟踪

正是通过这些入栈操作,来进行条件跳转的。

这是最后的内存空间布局。

现总结如下:

1)基类B的偏移表指针

2)基类B新增的数据成员

3)基类C的偏移表指针

4)基类C新增的数据成员

6)虚基类的数据成员

1.8菱形继承,有虚函数,为虚继承的情况

相较于1.7,这里增加了虚函数,那么又有什么不同呢?

根据这些,大概猜测其内存空间布局如下:

1)基类B的虚表指针

2)基类B的偏移表指针

3)基类B的数据成员

4)基类C的虚表指针

5)基类C的偏移表指针

6)基类C的数据成员

7)派生类D的虚表指针(后证实,不是这样的,而是分割)

8)派生类D的数据成员

9)虚基类A的虚表

10)虚基类A的数据成员

下面来一一查看。

设置偏移表。

偏移表的设置,在虚表设置之前。

这里的偏移表的第二项,用于确定本类(B)对虚基类(A)的定位。

而第一项,像是本类的虚表指针相对于偏移表的偏移。

这里有分割线的概念,用于分割非虚基类和虚基类。

此时,对于两个虚表,有点疑惑

至此,完成了对内存空间布局的更新,现总结如下:

a)B新增的虚函数

b)D新增的虚函数

2)基类B的偏移表指针

3)基类B新增的数据成员

4)基类C的虚表指针

a)C新增的虚函数

5)基类C的偏移表指针

6)基类C新增的数据成员

7)派生类D新增的数据成员

8)分割

9)虚基类的虚表指针

a)A未被覆盖的虚函数

b)D覆盖的虚函数

10)虚基类的数据成员

所以,这里各虚表的特点是——仅存放新增的虚函数地址。

至于那些覆盖的,则放在虚基类的虚表中。

上面这些,

是以菱形继承为基础,控制有无虚函数,是否为虚继承,所进行的测试。

2.总结

现在来试着从更全面的角度来看,试图总结它们的规律。

2.1无虚函数,仅有数据成员的情况

1.1,1.3,1.5的布局都很相似——基类数据成员、派生类新增的数据成员

按照这样的顺序进行排放。

而在1.7的情境中,因虚基类的存在,仅存一份拷贝,引入偏移表。

2.2有虚函数的情况

这是

虚函数的存在,引入了虚表。

可见它们也大致遵循着类似的规则:

1)虚表指针,偏移表指针,数据成员

2)原数据成员,新增数据成员

3)原虚函数,新增的虚函数

2.3其他情况

上面大致描述了一些基本框架情况,在此基础上还可以有其他的变形。

比如:

1)多重继承中,A,B——>

CA没有虚函数,B有虚函数

这对内存空间布局的影响

B的虚表指针,

B的数据成员,

A的数据成员,

C新增的数据成员

2)单单两个类间的虚继承

A——>

virtualB

a)无虚函数的情况

B的偏移表指针

B新增的数据成员

虚基类A的数据成员

b)有虚函数的情况

这还要看是否发生覆盖,如果没有覆盖:

虚基类A的虚表指针

如果有了覆盖:

B的偏移指针

分割

其他不再详述。

2.4覆盖、新增

在虚继承中,有分割这么一说——用0x00000000来分割非虚基类和虚基类。

但是,分割是否出现,这还取决于是否新增了虚函数。

其实,对于虚函数,都存在覆盖和新增的视角处理。

这涉及到对虚表的更新处理。

2.5本类的虚表

可以这么说,在继承中是不存在本类的虚表这么一说的。

都是在其基类的虚表基础之上,或进行覆盖,或进行新增。

当然了,一般的,新增的虚函数地址,是存放在第一个基类虚表里的。

2.6偏移表,虚表

偏移表中一般两项,第二项用于本类对虚基类的定位,是偏移相关。

而第一项,好像是本类的虚表相对于本类偏移表的偏移。

当本类没有虚表时,第一项就是0。

当本类的虚表在偏移之上时,该值为负,刚好是它们间的差值。

(一般如此)

为正的情况呢?

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1