现在的位置: 首页 > 综合 > 正文

C++ 虚继承与普通继承的内存模型对比

2013年12月05日 ⁄ 综合 ⁄ 共 1708字 ⁄ 字号 评论关闭

实验小结:对虚继承中编译器不同内存分配也不同。
//1.vc6.0中虚继承除了自己有虚函数时有虚指针(没有虚函数时就不加自身的这个虚指针)+另外还有添加一个“公用继承虚指针”+再加上基的空间
//2.gcc或codeblock中就没有添加“公用继承虚指针”,会比vc6.0中少4位,但如有虚函数时就有虚指针,最后还要加上基的空间 //相比1.少了4
//3.对于不是虚继承而是一把的继承就会没有“公用继承虚指针”,同时也不会在每个派生类中 如有虚函数时还添加虚指针,即基类与派生类公用一个虚指针,最后再加上其他存储区 //再相比1.少了8

下面是网上的一个简单例子:(VC6.0下)

C++2.0以后全面支持虚函数与虚继承,这两个特性的引入为C++增强了不少功能,也引入了不少烦恼。虚函数与虚继承有哪些特性,今天就不记录了,如果能搞了解一下编译器是如何实现虚函数和虚继承,它们在类的内存空间中又是如何布局的,却可以对C++的了解深入不少。这段时间花了一些时间了解这些玩意,搞得偶都,不过总算有些收获,嘿嘿。

先看一段代码
class A
{
virtual aa(){};
};

class B : public virtual A
{
char j[3]; //加入一个变量是为了看清楚class中的vfptr放在什么位置
public:
virtual bb(){};
};
class C : public virtual B
{
char i[3];
public:
virtual cc(){};
};

分析一下,也好加强一下印象。
1、对于class A,由于只有一个虚函数,那么必须得有一个对应的虚函数表,来记录对应的函数入口地址。同时在class A的内存空间中之需要有个vfptr_A指向该表。sizeof(A)也很容易确定,为4。
2、对于class B,由于class B虚基础了class A,同时还拥有自己的虚函数。那么class B中首先拥有一个vfptr_B,指向自己的虚函数表。还有char j[3],做一次alignment,一般大小为4。可虚继承该如何实现咧?this is 啊 problem!偶之前是不晓得的,还好C++ Object Model上有介绍。首先要通过加入一个虚类指针(记vbptr_B_A)来指向其父类,然后还要包含父类的所有内容。有些复杂了,不过还不难想象。sizeof(B)=
4+4+4+4=16(vfptr_B、char j[3]做alignment、vbptr_B_A和class A)。
3、在接着是class C了。class C首先也得有个vfptr_C,然后是char i[3],然后是vbptr_C_B,然后是class B,所以sizeof(C)=4+4+4+16=28(vfptr_C、char i[3]做alignment、vbptr_C_A和class B)。

 

举例:(注意虚拟继承中缺少一个指向父类的指针)

class X

{

public:

    int i;

    virtualvoid xx(){}

};

vptr

data

Int i

 

class A
public virtual X  

{

public:

    int j;

    virtual void aa(){}

};

vptrA

dataA

Int j;

vptrX

dataX

Int i;

  

class AA
public X 

{

public:

    int j;

    virtual void aa(){}

};

vptrX

dataXX

Int i;

dataAA

Int j;

  

class C
public virtual A, public virtual B

{

public:

    int k;

    virtualvoid cc(){}

};

 

vptrC

 

dataC

Int k;

 

vptrA

 

dataA

Int j;

 

vptrX

 

dataX

Int i;

 

vptrB

dataB

double d;

  

class CC
public AA, public BB

{

public:

    int k;

    virtualvoid cc(){}

};

vptrXX

dataXX

Int i;

dataAA

Int j;

vptrXX

dataXX

Int i;

抱歉!评论已关闭.