首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

派生类占用内存大小,该怎么解决

2013-12-17 
派生类占用内存大小本帖最后由 Jeter_Lin 于 2013-12-15 19:02:23 编辑#includeiostreamusing namespace

派生类占用内存大小
本帖最后由 Jeter_Lin 于 2013-12-15 19:02:23 编辑 #include<iostream>
using namespace std;
 
class B
{
 public:
virtual void bf(){}
   virtual ~B(){ cout <<"B::~B()"<<endl; }
};
 
class D:public B
{

 char d;
  public:

   virtual ~D() { cout <<"D::~D()"<<endl; }
};
int main(void)
{

cout << "sizeB:" << sizeof(B) << " sizeD:"<< sizeof(D) <<endl;
   return 0;
}
代码如上,问题如下
D类如果不继承B类,其sizeof结果是8,因为是D类需要保存虚函数表的指针vfptr(4字节),于是其中的变量char d因为字节对齐缘故需要补齐到4字节,问题在于,D类继承B类后,sizeof结果依旧是8,按照网上很多相关文章的说法,此时D类应该是自身的大小加上基类的大小,即8+4=12才对,这是什么原因呢?
P.S.我是在ubuntu 12.04下用其自带的G++编译执行的                                        
[解决办法]

引用:

class D size(8):
        +---
        
[解决办法]
 +--- (base class B)
 0      
[解决办法]
 
[解决办法]
 {vfptr}
        
[解决办法]
 +---
 4      
[解决办法]
 d
        
[解决办法]
 <alignment member> (size=3)
        +---

第一次看到这种编译器的打印信息,在这里的vfptr是指D类的虚函数表指针吧,B类的虚函数表指针也是它么?还是说B类的虚函数表指针并没有复制进D类来呢?

你是不是误会什么了,这个虚函数表并非是指D类的。一个类的虚函数表保管的是它本身以及继承的虚函数的情况,所以应该从最顶层开始维护。如果遇到派生类重名的虚函数就会覆盖虚函数表中的虚函数,如果原本没有就会加入这张表中,一直到该类本身。

如果是单继承就只有1个虚函数表,如果是多继承则会有多个。给你看个例子:
class A
{
 public:
virtual void bf(){}
virtual ~A(){}
};
 
class B:public A
{
 public:
virtual void bf(){}
virtual ~B(){ cout <<"B::~B()"<<endl; }
};

class C:public A
{
 public:
virtual void bf(){}
virtual ~B(){ cout <<"B::~B()"<<endl; }
};
 
class D:public B,class C
{
char d;
public:
virtual ~D() { cout <<"D::~D()"<<endl; }
};

class D size(12):
        +---
        
[解决办法]
 +--- (base class B)
        
[解决办法]
 
[解决办法]
 +--- (base class A)
 0      
[解决办法]
 
[解决办法]
 
[解决办法]
 {vfptr}
        
[解决办法]
 
[解决办法]
 +---
        
[解决办法]
 +---
        
[解决办法]
 +--- (base class C)
        
[解决办法]
 
[解决办法]
 +--- (base class A)
 4      
[解决办法]
 
[解决办法]
 
[解决办法]
 {vfptr}
        
------解决方案--------------------


 
[解决办法]
 +---
        
[解决办法]
 +---
 8      
[解决办法]
 d
        
[解决办法]
 <alignment member> (size=3)
        +---

D::$vftable@B@:
        
[解决办法]
 &D_meta
        
[解决办法]
  0
 0      
[解决办法]
 &B::bf
 1      
[解决办法]
 &D::{dtor}

D::$vftable@C@:
        
[解决办法]
 -4
 0      
[解决办法]
 &C::bf
 1      
[解决办法]
 &thunk: this-=4; goto D::{dtor}

D::{dtor} this adjustor: 0
D::__delDtor this adjustor: 0
D::__vecDelDtor this adjustor: 0


看表中的图,虚函数表全部都是从最顶层的class A开始的,然后因为继承了2个class所以有两个vfptr

当然这个还是简单的,把这个例子修改下,用virtual继承,这就是著名的菱形继承问题,你和上面那个对比下:

class A
{
 public:
virtual void bf(){}
virtual ~A(){}
};
 
class B:virtual public A
{
 public:
virtual void bf(){}
virtual ~B(){ cout <<"B::~B()"<<endl; }
};

class C:virtual public A
{
 public:
virtual void bf(){}
virtual ~B(){ cout <<"B::~B()"<<endl; }
};
 
class D:public B,class C
{
char d;
public:
virtual ~D() { cout <<"D::~D()"<<endl; }
};

class D size(20):
        +---
        
[解决办法]
 +--- (base class B)
 0      
[解决办法]
 
[解决办法]
 {vbptr}
        
[解决办法]
 +---
        
[解决办法]
 +--- (base class C)
 4      
[解决办法]
 
[解决办法]
 {vbptr}
        
[解决办法]
 +---
 8      
[解决办法]
 d
        
[解决办法]
 <alignment member> (size=3)
        +---
12      
[解决办法]
 (vtordisp for vbase A)
        +--- (virtual base A)
16      
[解决办法]
 {vfptr}
        +---

D::$vbtable@B@:
 0      
[解决办法]
 0
 1      
[解决办法]
 16 (Dd(B+0)A)

D::$vbtable@C@:
 0      
[解决办法]
 0
 1      
[解决办法]
 12 (Dd(C+0)A)

D::$vftable@:
        
[解决办法]
 -16
 0      
[解决办法]
 &(vtordisp) thunk: this-=8; goto B::bf
 1      
[解决办法]
 &(vtordisp) D::{dtor}

D::{dtor} this adjustor: 16
D::__delDtor this adjustor: 16
D::__vecDelDtor this adjustor: 16

热点排行