指针表示基类的虚函数表--4字节
指针表示仅属于派生类的虚函数Func2()--4字节(就我而言,派生类没有非虚基类并得到其独有的虚函数应该有自己的虚表)
啊,我现在看到了问题。这不是虚拟函数表的工作方式。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
的虚函数表,事实上,这正是虚函数发挥作用的方式。
(到处都是假设,这些都没有明确定义,虚拟继承使事情复杂化,等等等等)