C++虚函数表(多态的实现原理)
“多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定。这是如何实现的呢?
请看下面的程序,该程序演示了多态类对象存储空间的大小。
#include <iostream> using namespace std; class A { public: int i; virtual void func() {} virtual void func2() {} }; class B : public A { int j; void func() {} }; int main() { cout << sizeof(A) << ", " << sizeof(B); //输出 8,12 return 0; }
在 32 位编译模式下,程序的运行结果是:
8, 12
如果将程序中的 virtual 关键字去掉,输出结果变为:
4, 8
对比发现,有了虚函数以后,对象所占用的存储空间比没有虚函数时多了 4 个字节。实际上,任何有虚函数的类及其派生类的对象都包含这多出来的 4 个字节,这 4 个字节就是实现多态的关键——它位于对象存储空间的最前端,其中存放的是虚函数表的地址。
每一个有虚函数的类(或有虚函数的类的派生类)都有一个虚函数表,该类的任何对象中都放着该虚函数表的指针(可以认为这是由编译器自动添加到构造函数中的指令完成的)。
虚函数表是编译器生成的,程序运行时被载入内存。一个类的虚函数表中列出了该类的全部虚函数地址。例如,在上面的程序中,类 A 对象的存储空间以及虚函数表(假定类 A 还有其他虚函数)如图 1 所示。
发表评论