我在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的结果,即:
Func2()指针表示仅属于派生类-4字节的虚函数(据我所知,没有非虚拟基类并获得其唯一虚拟函数的派生类应该有自己的虚拟表)。之和可达20个字节;
然而,Xcode 4.6产生了sizeof(Derived)==16的不同结果,我是否弄错了?
发布于 2013-08-22 19:51:18
指针表示基类的虚函数表-4字节 指针表示仅属于派生类-4字节的虚拟函数Func2() (据我所知,派生类没有非虚拟基类并获得其唯一的虚拟函数,因此应该有自己的虚拟表)。
啊,我现在看到问题了。这并不完全是虚拟函数表的工作方式。定义Base时,编译器会注意到它需要一个虚拟表,并为Base生成一个虚拟表,其中有一个指针(Func),指向Base::Func实现。定义Derived时,编译器会注意到它继承自Base,并为Base生成一个函数表,该表有两个指针,Func指向Derived::Func,Func2指向Derived::Func2。
然后,如果创建了Base的一个实例,您在Base表中提到的函数表指针,对Func的任何调用都将被重定向到Base::Func。
如果创建了Derived的实例,则它的内部Base对象的虚拟函数表指针将指向Derived表。Base只知道如何访问Func指针,但是Func指针现在指向Derived::Func,所以这就是get的名称。它没有意识到它指的是另一张桌子。在代码中,它可能看起来更像这样:
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所以XCode是对的。Derived正在“劫持”Base的虚拟函数表,实际上,这正是虚拟函数的神奇之处。
(随处可见的假设,这些都是定义不清的,虚拟继承使事情复杂化等等)
https://stackoverflow.com/questions/18389356
复制相似问题