1
class RootBase{
public:
    RootBase():ai(12){}
    virtual void fas(){
        printf("%p \n", this);
    }
private:
    int ai;

};

class Base : virtual public RootBase{

public:
    Base():bai(1){}

    virtual void fas(){

    }
    virtual void fa(){

    }
private:
    int bai;
};

Base *pBase = new Base; 

我测试了关于类的内存位置的虚拟继承关系案例。结果让我吃惊,因为 Base 的大小是 24 字节。我可以理解包括虚函数表指针、虚基表指针和成员变量的 20 个字节。

pBase指向的Base对象的内存分布为:

 60 77 41 00 68 77 41 00 01 00 00 00 00 00 00 00 54 77 41 00 0c 00 00 00

但我无法理解第 13-16 个字节的含义, 0x00000000 ,a NULL(integer 0 in x86 32bit) 。四个字节 0 有什么作用?(操作系统:win xp,IDE:visual studio 8.0)

我也认为整数 0 代表对齐填充,但没有理由填充到 8 个字节。

4

1 回答 1

4

这直接取自您所描述的类的对象布局转储。我希望它能回答你的问题。从更多的研究中,我发现vtordisp对于 class Base。是从使用虚基声明的类的构造函数或析构函数调用虚函数时使用的偏移量。显然是告诉他们你的虚函数表在哪里。

来自MSFT 的 Jonathan Caves, 5 年前:

它很少使用——但我们必须将它添加到从虚拟基类继承的类中并覆盖虚拟函数,以防用户在构造函数或析构函数中调用虚拟函数。

1>注意:对所有行的序言感到抱歉。怪微软,它是他们的工具。

1>  class RootBase  size(8):
1>      +---
1>   0  | {vfptr}
1>   4  | ai
1>      +---
1>  
1>  RootBase::$vftable@:
1>      | &RootBase_meta
1>      |  0
1>   0  | &RootBase::fas
1>  
1>  RootBase::fas this adjustor: 0
1>  
1>  
1>  class Base  size(24):
1>      +---
1>   0  | {vfptr}
1>   4  | {vbptr}
1>   8  | bai
1>      +---
1>  12  | (vtordisp for vbase RootBase)
1>      +--- (virtual base RootBase)
1>  16  | {vfptr}
1>  20  | ai
1>      +---
1>  
1>  Base::$vftable@Base@:
1>      | &Base_meta
1>      |  0
1>   0  | &Base::fa
1>  
1>  Base::$vbtable@:
1>   0  | -4
1>   1  | 12 (Based(Base+4)RootBase)
1>  
1>  Base::$vftable@RootBase@:
1>      | -16
1>   0  | &(vtordisp) Base::fas
1>  
1>  Base::fas this adjustor: 16
1>  Base::fa this adjustor: 0
1>  
1>  vbi    class     offset   o.vbptr  o.vbte fVtorDisp
1>         RootBase      16        4       4          1

采用完全相同的代码,但制作RootBase常规基类(即 not virtual public RootBase just public RootBase)对对象布局有显着影响:

1>  class RootBase  size(8):
1>      +---
1>   0  | {vfptr}
1>   4  | ai
1>      +---
1>  
1>  RootBase::$vftable@:
1>      | &RootBase_meta
1>      |  0
1>   0  | &RootBase::fas
1>  
1>  RootBase::fas this adjustor: 0
1>  
1>  
1>  class Base  size(12):
1>      +---
1>      | +--- (base class RootBase)
1>   0  | | {vfptr}
1>   4  | | ai
1>      | +---
1>   8  | bai
1>      +---
1>  
1>  Base::$vftable@:
1>      | &Base_meta
1>      |  0
1>   0  | &Base::fas
1>   1  | &Base::fa
1>  
1>  Base::fas this adjustor: 0
1>  Base::fa this adjustor: 0

请注意,随着虚拟基础的消失,不再存储“我是谁”偏移量,这似乎可以很好地清理对象格式。

于 2013-01-05T04:27:20.287 回答