前面我们已经知道, 在没有虚函数的时候, 对象的大小就是对应的成员变量的大小, 而成员函数不会占用对象的空间, 今天我们来讨论一下, 当类中定义了虚函数的时候, 此时对象的大小以及对象模型
非继承下的对象模型
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;
};
此时的对象模型如下图所示