具有虚拟基础和虚函数的sizeof派生类

时间:2013-08-22 19:36:18

标签: c++ function virtual-inheritance

我遇到了C ++虚拟继承问题。

我有一个类层次结构如下:

class Base
{
public:
    virtual void Func(){};
    int BaseValue;
};

class Derived : virtual public Base
{
public:
    void Func(){};
    virtual void Func2(){};
    int DerivedValue;
};

然而,编译得很好,我对内存结构有点困惑。

我希望获得sizeof(Derived)==20的结果,即:

  1. BaseValue和DerivedValue - 8个字节
  2. 指针表示基类的成员偏移量 (虚拟继承的功能) - 4个字节 < / LI>
  3. 指针表示基类的虚函数表--4个字节
  4. 指针表示虚拟函数Func2(),它只属于Derived类 - 4个字节 (据我所知,没有非虚拟基类并获得其独特虚函数的派生类应该有自己的虚拟表)
  5. 总计最多20个字节;

    然而Xcode 4.6产生了sizeof(Derived)==16的不同结果,我弄错了吗?

1 个答案:

答案 0 :(得分:1)

  

指针表示基类的虚函数表 - 4个字节
  指针表示仅属于的虚函数Func2()   class Derived - 4个字节(据我所知,派生类是哪个   没有非虚拟基类并获得其独特的虚函数   应该有自己的虚拟表)

啊,我现在看到了问题。这不是完全虚函数表的工作原理。定义Base时,编译器会注意到它需要一个虚拟表,并为Base生成一个虚拟表,其中一个指针(Func)指向Base::Func实现。定义Derived时,编译器会通知它继承自Base,并为Base生成一个具有两个指针的函数表,Func个点至Derived::FuncFunc2指向Derived::Func2

然后,如果创建了Base的实例,那么你在Base表中提到点的函数表指针,对Func的任何调用都将被重定向到{{1 }}。

如果创建了Base::Func的实例,则它的内部Derived对象的虚函数表指针将指向Base表。 Derived只知道如何访问Base指针,但Func指针现在指向Func,这就是所谓的调用。它没有意识到它指向一个不同的表。在代码中,它可能看起来更像这样:

Derived::Func

所以XCode是对的。 using voidFunctionType = void(*)(); struct BaseVTable { voidFunctionType Func; }BaseVTableGlobal; struct Base { Base() :vTable(&BaseVTableGlobal) {} void Func() {vTable->Func();} BaseVTable* vTable; //4 bytes int BaseValue; //4 bytes }; //total is 8 bytes struct DerivedVTable : public BaseVTable { voidFunctionType Func; voidFunctionType Func2; }DerivedVTableGlobal; //inherits 8 bytes, +4 for virtual inheritance = 12 struct Derived : virtual public Base { Derived() :Base() {vTable = &DerivedVTableGlobal;} //the shared vTable points at DerivedVTableGlobal void Func() {vTable->Func();} //base knows about Func, so this is easy void Func2() {((DerivedVTable*)vTable)->Func2();} //base doesn't know about Func2 int DerivedValue; //4 bytes }; //16 bytes total 是“劫持”Derived的虚拟功能表,事实上,正好虚拟功能如何发挥其魔力。

(各地的假设,这些都没有明确定义,虚拟遗骸使事情变得复杂等等)