前面我们已经知道, 在没有虚函数的时候, 对象的大小就是对应的成员变量的大小, 而成员函数不会占用对象的空间, 今天我们来讨论一下, 当类中定义了虚函数的时候, 此时对象的大小以及对象模型
非继承下的对象模型
class Base
{
public:virtual void func1(){cout << "Base::func1()" << endl;}virtual void func2(){cout << "Base::func2()" << endl;}
private:int a;
};
void Test1()
{Base b1;
}
此时打开编译器, 观察 b1 的对象模型如下图所示
此时我们会发现对象b1 它除了有一个成员变量 a 之外, 它还有一个虚函数表, 这个虚函数表的数据结构是由一个指针数组来维护的, 这个指针数组中存放了指向虚函数的指针, 并且指向虚函数指针的结束标识在VS下是以一个0为结束标识, 也就是说 b1的对象模型如下图所示
单继承下的对象模型
class Base
{
public:virtual void func1(){cout << "Base::func1()" << endl;}virtual void func2(){cout << "Base::func2()" << endl;}
private:int a;
};class Derive :public Base
{
public:virtual void func1(){cout << "Derive: func1()" << endl;}virtual void func3(){cout << "Derive: func3()" << endl;}virtual void func4(){cout << "Derive: func4()" << endl;}
private:int b;
};typedef void(*VFUNC)();void PrintVTable(int* VTable)
{cout << "虚表地址: " << VTable << endl;int i = 0;for(; VTable[i] != 0; i++){printf("第 %d 个虚函数地址: 0x%x -> ", i, VTable[i]);VFUNC f = (VFUNC)VTable[i];f();}cout << endl;
}void Test1()
{Base b1;Derive d1;int*VTable1 = (int*)(*(int*)(&b1));int*VTable2 = (int*)(*(int*)(&d1));PrintVTable(VTable1);PrintVTable(VTable2);
}
为了方便起见, 我们将对应的虚表打印出来, 此时会发现如下现象
接下来探索一下对应的 b1 和 d1 的对象模型
多继承对象模型
class Base1
{
public:virtual void func1(){cout << "Base1::func1()" << endl;}virtual void func2(){cout << "Base1::func2()" << endl;}
private:int b1;
};class Base2
{
public:virtual void func1(){cout << "Base2::func1()" << endl;}virtual void func2(){cout << "Base2::func2()" << endl;}
private:int b2;
};
class Derive :public Base1, public Base2
{
public:virtual void func1(){cout << "Derive: func1()" << endl;}virtual void func3(){cout << "Derive: func3()" << endl;}
private:int b;
};
此时的对象模型如下图所示