虚拟推导的多态类的大小

Size of polymorphic class derived virtually

本文关键字:多态 虚拟      更新时间:2023-10-16

我很难理解以下类的大小是什么?
我使用的是 MSVS 2008(VC 9.0 编译器)。我已经读到,如果我不声明虚函数(在下面的示例中),那么 D 类将包含 2 个额外的指针(1 个来自 B,另一个来自 C),它们将指向 A 的共享实例。

但是在下面的情况下,每个类的内存映射是什么(也有虚函数)?

class A
{
public:
    int a;
    virtual void Func();
public:
    A(void);
    ~A(void);
};
class B :virtual public A
{
public:
    int b;
    virtual void Func();
public:
    B(void);
    ~B(void);
};
class C: virtual public A
{
public:
    int c;
    virtual void Func();
public:
    C(void);
    ~C(void);
};
class D : public B, public C
{
public:
    int d;
    virtual void Func();
public:
    D(void);
    ~D(void);
};


int _tmain(int argc, _TCHAR* argv[])
{
    cout << "size of Class A :" << sizeof(A) << endl;
    cout << "size of Class B :" << sizeof(B) << endl;
    cout << "size of Class C :" << sizeof(C) << endl;
    cout << "size of Class D :" << sizeof(D) << endl;
    return 0;
}

输出:
A类尺寸:8
B类尺寸:20
C级尺寸:20
D类尺寸:32

在这里,B,C和D的大小是如何计算的?

编辑:以下是每个类的/d1reportSingleClassLayoutXXX编译器选项生成的内存映射:

1>class A size(8):  
1> +---  
1> 0 | {vfptr}  
1> 4 | a  
1>class B size(20):  //Similar for C
1> +---  
1> 0 | {vbptr}  
1> 4 | b  
1> +---  
1>8 | (vtordisp for vbase A)  
1> +--- (virtual base A)  
1>12 | {vfptr}  
1>16 | a  
1> +---  
1>class D size(32):  
1> +---  
1> | +--- (base class B)  
1> 0 | | {vbptr}  
1> 4 | | b  
1> | +---  
1> | +--- (base class C)  
1> 8 | | {vbptr}  
1>12 | | c  
1> | +---  
1>16 | d  
1> +---  
1>20 | (vtordisp for vbase A)  
1> +--- (virtual base A)  
1>24 | {vfptr}  
1>28 | a    

vbase X 的 vtordisp 在这里是什么意思?

我会

说你在一台 32 位机器上,sizeof(int)是 4。

推测性地:

一、A的大小:

|int a (4)|vtable pointer A (4)|

二、B和C的大小:

|A base instance (8)|pointer to A(4)|int b/c(4)|vtable pointer B/C|

三、D的大小:

|A base instance (8)|pointer to A(4)|int c(4)|vtable pointer B(4)|pointer to A(4)|int d(4)|vtable pointer C(4)|

由于D实际上不是从C继承的,所以它可以重用vtable pointer C。同样,这只是猜测。您应该尝试转储对象 D 的内存以确保万无一失。而且我不确定你的机器如何对齐内存。

根据Jonathan Caves,MSFT

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

所以 - 这是MSVC(非常缺乏文档)的解决方案,用于"如何在对象构建期间进行虚拟调用?