C++继承时内存对象模型

这两篇博客都详细讲解了C++对象模型,链接如下:
http://www.cnblogs.com/QG-whz/p/4909359.html
http://www.cnblogs.com/jerry19880126/p/3616999.html

首先了解C++中一个类中的四种成员:
  1. 非静态数据成员被放在每一个对象体内作为对象专有的数据成员。
  2. 静态数据成员被提取出来放在程序的静态数据区内,为该类所有对象共享,只存在一份。
  3. 静态和非静态成员函数最终都被提取出来放在程序代码段中并为该类所有对象共享,因此每个成员函数也只能存在一份代码实体。C++中类的成员函数都是保存在静态存储区中,静态成员函数也是保存在静态存储区中,他们都是在类中保存同一个备份。
  4. 说明:构成对象本身的只有数据,任何成员函数都不隶属于任何一个对象,非静态成员函数与对象的关系就是this指针(this详细解释)。成员函数为该类所有对象共享,不仅是处于简化语言实现、节省存储的目的,而且是为了使同类对象有一致的行为。同类对象的行为虽然一致,但是操作不同的数据成员。

C++继承时内存对象模型

以下内容转载自:http://blog.csdn.net/randyjiawenjie/article/details/6693337

分为四种情况:
1.单继承
2.多继承(不含钻石继承)
3.非虚继承的钻石继承
4.虚继承的钻石继承
注:下面所有类中的函数都是虚函数。

1.单继承

单继承体系如下:


1.jpg

GrandChild对象的内存布局:


1.2.jpg

可见以下几个方面:
1)虚函数表在最前面的位置。
2)成员变量根据其继承和声明顺序依次放在后面。
3)在单一的继承中,被overwrite的虚函数在虚函数表中得到了更新。

2.多继承

多继承的体系如下:


2.jpg

Derive对象的内存布局如下:


2.2.jpg

我们可以看到:
1) 每个父类都有自己的虚表。
2) 子类的成员函数被放到了第一个父类的表中。
3) 内存布局中,其父类布局依次按声明顺序排列。
4) 每个父类的虚表中的f()函数都被overwrite成了子类的f()。这样做就是为了解决不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数。

出现钻石继承的虚继承的时候,虚基类在子类中只有一份。
出现钻石继承的非虚继承的时候,虚基类在每个子类中都有一份。

3.非虚继承的钻石继承

继承体系如下:


3.jpg

D的内存布局如下:


3.2.jpg

红色的部分就是重复的部分,就会造成二义性

4.虚继承的钻石继承(虚继承就是解决钻石继承问题的,如果不存在钻石继承,就不用虚继承)

继承体系如下:(红色专门标准虚继承)


4.jpg

D的内存布局如下:


4.2.jpg

可以看出,少了重合的部分。但是,代价是增加了一个虚函数指针

关于虚继承,多写一点儿

http://blog.csdn.net/xsh_123321/article/details/5956289
1.为什么需要虚继承
如下图所示如果访问Der::Fun or Der::m_nValue就会带来二义性,无法确定是调用Base1的还是Base2的,所以为了解决多重继承情况下成员访问的二义性,引入了虚继承机制。(说白了,虚继承就是共享继承,“共享”)

5.jpg

2.虚继承实现
在虚继承下,Der通过共享虚基类SuperBase来避免二义性,在Base1,Base2中分别保存虚基类指针,Der继承Base1,Base2,包含Base1, Base2的虚基类指针,并指向同一块内存区,这样Der便可以间接存取虚基类的成员,如下图所示:

5.2.jpg

3.不同编译器实现方式
不同编译器对间接存取的方法不同,以下以GCC和VC为例,均采用以下代码进行实验:

class SuperBase  
{  
public:  
    int m_nValue;  
    void Fun(){cout<<"SuperBase1"<<endl;}  
    virtual ~SuperBase(){}  
};  
class Base1:  virtual public SuperBase  
{  
public:  
virtual ~ Base1(){}  
};  
class Base2:  virtual public SuperBase  
{  
public:  
virtual ~ Base2(){}  
};  
class Der:public Base1, public Base2  
{  
public:  
virtual ~ Der(){}  
};  
void main()  
{  
cout<<sizeof(SuperBase)<<sizeof(Base1)<<sizeof(Base2)<<sizeof(Der)<<endl;  
}  

1) GCC中结果为8, 12, 12, 16
解析:sizeof(SuperBase) = sizeof(int) + 虚函数表指针
sizeof(Base1) = sizeof(Base2) = sizeof(int) + 虚函数指针 + 虚基类指针
sizeof(Der) = sizeof(int) + Base1中虚基类指针 + Base2虚基类指针 + 虚函数指针
GCC共享虚函数表指针,也就是说父类如果已经有虚函数表指针,那么子类中共享父类的虚函数表指针空间,不在占用额外的空间,这一点与VC不同,VC在虚继承情况下,不共享父类虚函数表指针,详见如下。
2)VC中结果为:8, 16, 16, 24
解析:sizeof(SuperBase) = sizeof(int) + 虚函数表指针
sizeof(Base1) = sizeof(Base2) = sizeof(int) + SuperBase虚函数指针 + 虚基类指针 + 自身虚函数指针
sizeof(Der) = sizeof(int) + Base1中虚基类指针 + Base2中虚基类指针 + Base1虚函数指针 + Base2虚函数指针 + 自身虚函数指针
如果去掉虚继承,结果将和GCC结果一样,A,B,C都是8,D为16,原因就是VC的编译器对于非虚继承,父类和子类是共享虚函数表指针的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容