C++学习之路: 虚继承的内存的模型

写给出结论:

1.类大小计算遵循结构体对其原则

2.类的大小与数据成员有关,与成员函数无关

3.类的大小与静态数据成员无关

4. 虚继承对类的大小影响

5.虚函数对类的大小影响

 

研究背景)

我们以这个钻石型继承来研究下,虚继承后派生类DD的内存分布,先说原理和推测,来理解编译器的处理是如何在内存上体现的。

保持我们一贯的做风。

#include <iostream>
using namespace std;

class BB
{
public:
    int bb_;
};

class B1 : virtual public BB
{
public:
    int b1_;
};

class B2 : virtual public BB
{
public:
    int b2_;
};

class DD : public B1, public B2
{
public:
    int dd_;
};

int main(void)
{
    cout<<sizeof(BB)<<endl;
    cout<<sizeof(B1)<<endl;
    cout<<sizeof(DD)<<endl;

    B1 b1;
    long** p;

    cout<<&b1<<endl;
    cout<<&b1.bb_<<endl;
    cout<<&b1.b1_<<endl;

    p = (long**)&b1;
    cout<<p[0][0]<<endl;
    cout<<p[0][1]<<endl;

    DD dd;
    cout<<&dd<<endl;
    cout<<&dd.bb_<<endl;
    cout<<&dd.b1_<<endl;
    cout<<&dd.b2_<<endl;
    cout<<&dd.dd_<<endl;
    p = (long**)&dd;
    cout<<p[0][0]<<endl;
    cout<<p[0][1]<<endl;
    cout<<endl;
    cout<<p[2][0]<<endl;
    cout<<p[2][1]<<endl;

    BB* pp;

    pp = &dd;
    pp->bb_;        // í¨1y???ó·??ê£??aDèòa??DDê±μ??§3?

    return 0;
}

结果打印

4
12
24
0xbfacd81c
0xbfacd824
0xbfacd820
0
134515772
0xbfacd804
0xbfacd818
0xbfacd808
0xbfacd810
0xbfacd814
12
-8

134515700
134515740

根据结果,我们可以把几个类的内存分布画出来

 

 

@B1的内存分布,可以通过照相记忆法。

有以下特点

1。 一般来说编译器都会把虚继承的基类放置在内存底部,和构造顺序是一致的,在小端机上是

高地址存放低字节,所以先构造bb_基类放置在底部。然后构造自身是B1

空白处世虚基类表指针,也占据4个字节

vbptr虚基类指针指向一个虚基类表,这个表记录着两个偏移量,

已在图上标注,*(指针和本地址的差) *(指针和虚基类的差),大家自己减一下就可以算出偏移量分布式0和8;

 

@DD对象:多虚基类继承下的内存分布

可以看的出内存分布和和继承,与构造顺序的关系,基类总是先被构造,继承离最远派生类越远,越先构造,所以看到,基类BB最先被构造,然后是B2,最后是B1。

当B1构造结束,那么整个DD类便构造完成了

 

结论:通过派生类指针访问虚基类数据成员,需要在运行时动态的找到偏移地址,

数据间接访问。

时间: 2024-10-11 11:07:50

C++学习之路: 虚继承的内存的模型的相关文章

转载:C++ 多继承和虚继承的内存布局

C++ 多继承和虚继承的内存布局[已翻译100%] 英文原文:Memory Layout for Multiple and Virtual Inheritance 标签: <无> run_mei 推荐于 4年前 (共 14 段, 翻译完成于 10-17) 评论 46 分享 收藏 198 参与翻译 (5人) : super0555, polarisxxm, Ley, zaobao, 开源中国吹牛第一仅中文 | 中英文对照 | 仅英文 | 打印此文章 警告. 本文有点技术难度,需要读者了解C++和

多重继承和虚继承的内存布局

这篇文章主要讲解虚继承的C++对象内存分布问题,从中也引出了dynamic_cast和static_cast本质区别.虚函数表的格式等一些大部分C++程序员都似是而非的概念.原文见这里(By Edsko de Vries, January 2006) 敬告: 本文是介绍C++的技术文章,假定读者对于C++有比较深入的认识,同时也需要一些汇编知识. 本文我们将阐释GCC编译器针对多重继承和虚拟继承下的对象内存布局.尽管在理想的使用环境中,一个C++程序员并不需要了解这些编译器内部实现细节,实际上,

C++ 多继承和虚继承的内存布局(Memory Layout for Multiple and Virtual Inheritance)

警告. 本文有点技术难度,需要读者了解C++和一些汇编语言知识. 在本文中,我们解释由gcc编译器实现多继承和虚继承的对象的布局.虽然在理想的C++程序中不需要知道这些编译器内部细节,但不幸的是多重继承(特别是虚拟继承)的实现方式有各种各样的不太明确的结论(尤其是,关于向下转型指针,使用指向指针的指针,还有虚拟基类的构造方法的调用命令). 如果你了解多重继承是如何实现的,你就能预见到这些结论并运用到你的代码中.而且,如果你关心性能,理解虚拟继承的开销也是非常有用的.最后,这很有趣. :-) 多重

C++ 多继承和虚继承的内存布局(转)

转自:http://www.oschina.net/translate/cpp-virtual-inheritance 警告. 本文有点技术难度,需要读者了解C++和一些汇编语言知识. 在本文中,我们解释由gcc编译器实现多继承和虚继承的对象的布局.虽然在理想的C++程序中不需要知道这些编译器内部细节,但不幸的是多重继承(特别是虚拟继承)的实现方式有各种各样的不太明确的结论(尤其是,关于向下转型指针,使用指向指针的指针,还有虚拟基类的构造方法的调用命令). 如果你了解多重继承是如何实现的,你就能

虚继承的内存布局手札1——基于VS2012

1.纸上得来总觉浅,低头debug才深刻. 对于<深度探索C++对象模型>这类型的书,得到的知识要去及时巩固才能实现永久记忆. 2.在实现了了虚拟继承归并分支之后的内容布局跟虚表的可复用存在极大关系. 继承的顺序决定了A和B的布局顺序,然后Common则在高地址,即公虚基类的布局放在D的尾部. 情况1: class A:public virtual Common{...}; class B:public virtual Common{...;virtual void NotInCommon()

[原创]java WEB学习笔记87:Hibernate学习之路-- -映射 继承关系(subclass , joined-subclass,union-subclass )

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

虚继承之单继承的内存布局(VC在编译时会把vfptr放到类的头部,这和Delphi完全一致)

C++2.0以后全面支持虚函数与虚继承,这两个特性的引入为C++增强了不少功能,也引入了不少烦恼.虚函数与虚继承有哪些特性,今天就不记录了,如果能搞了解一下编译器是如何实现虚函数和虚继承,它们在类的内存空间中又是如何布局的,却可以对C++的了解深入不少.这段时间花了一些时间了解这些玩意,搞得偶都,不过总算有些收获,嘿嘿. 先看一段代码class A{      virtual aa(){};}; class B : public virtual  A{      char j[3];      

[转载]多重继承及虚继承中对象内存的分布

粘过来的效果还不错:) 本位通过不断地完善讲解多重继承及虚继承中对象内存的分布. 读的时候不要着急,第一遍会有些晕,第二遍就会好很多. 能帮助加深对多重继承及虚继承对象内存的分布情况. 多重继承及虚继承中对象内存的分布     这篇文章主要讲解G++编译器中虚继承的对象内存分布问题,从中也引出了dynamic_cast和static_cast本质区别.虚函数表的格式等一些大部分C++程序员都似是而非的概念. 本文是介绍C++的技术文章,假定读者对于C++有比较深入的认识,同时也需要一些汇编知识.

c++内存部局(虚继承)

最近又重新温习了一下深度探索c++对象模型,中虚拟继承虚表的实现,为了弄清虚表的内存部局情况特写此测试程序. 测试程序分别在windows vs2012下,与linux gcc 4..4.7 20120313 redhat4.4.7-4下 windows vs2012 上图中的偏移为-4表明存在vptr,如果为0说明没有vptr,下面的程序可以说明,而且从图中可以看出虚表中不会有重复的选项 #include <iostream> using namespace std; class X{ pu