4

使用虚拟继承时类的大小如下..

ABase=4(sizeof imem)
BBase=12(sizeof imem+ABase+VBase_ptr)
CBase=12(sizeof imem+ABase+VBase_ptr) 

这是有道理的,但我不明白为什么大小ABCDerived是 24。

class ABase{ 
        int iMem; 
}; 

class BBase : public virtual ABase { 
        int iMem; 
}; 

class CBase : public virtual ABase { 
        int iMem; 
}; 

class ABCDerived : public BBase, public CBase { 
        int iMem; 
}; 
4

2 回答 2

5

这将非常依赖于平台,但我认为我们可以理解发生了什么。

首先,标准没有指定如何实现虚拟继承。就标准而言,甚至没有像 vtable 这样的东西。

ABCDerivedBBaseCBase每一个都由一个int. 还有一个实例ABaseint. 最后有一个 vtable ptr。

an 的大小int取决于平台——它不一定是 4 个字节。但是如果我们假设它是 4 个字节,并且 vtable 的大小也是 4 个字节,我们有:

int  [ABCDerived] = 4 bytes
int  [CBase]      = 4 bytes
int  [BBase]      = 4 bytes
int  [ABase]      = 4 bytes
vtable            = 4 bytes
                 -------------
                   20 bytes

然而,这并不意味着sizeof (ABCDerived)是 20。对齐也在这里发挥作用。该标准允许编译器增加对象的大小,以便该大小可以被多个整字整除。

考虑:

class ABase{ 
            int iMem; 
}; 

class BBase : public virtual ABase { 
            int iMem; 
}; 

class CBase : public virtual ABase { 
            int iMem; 
}; 

class ABCDerived : public BBase, public CBase { 
            int iMem; 
}; 

int main()
{
    ABCDerived d;
    BBase& b = d;
    ABase* ab = &b; 
    CBase& c = d;
    ABase* ac = &b; 

    cout << hex << (void*) ab << "\n"
        << hex << (void*) ac << "\n";

    cout << sizeof (d) << "\n" << sizeof (int) << "\n";
}

输出28在我的 64 位 Linux 机器上。

但是,如果我打开打包(使用平台相关的#pragma 开关):

#pragma pack (1)

输出现在是 20。

所以,这一切的长短是:

这里有大量依赖于平台的东西。您不能说对象的大小是这样或那样,至少在不使用更多依赖于平台的东西并且不知道您的编译器如何实际实现虚拟继承的情况下。它的大小是它的大小。

于 2013-08-02T16:08:37.757 回答
0

大小应为 20,因为您使用虚拟继承 ABCDerived 不会继承 ABase IMem 两次。正如您所说的那样,它给出了 24,可能是您的编译器不支持虚拟继承。

于 2013-08-02T15:56:20.933 回答