多重继承下的虚函数表 多态是C++语言中的一项重要的机制,虚函数就是为实现多态而设计的。多态就是用父类型的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态” 。而虚函数表在这种多态机制中起了核心调度的作用。由于是编译器在后台操作,所以它被蒙上了一层神秘的面纱。 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为VFTable。 在这个表中,主要是一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,VFTable 就显得尤为重要了,它就像一个地图一样,指明了实际所应该调用的函数。在C++的标准中提到,编译器必需要保证虚函数表的指针存在于对象实例中最前面的位置。 这意味着我们通过对象实例的地址得到它的VFTable,然后就可以遍历其中函数指针,并调用相应的函数。 Code 1: class Base { public: virtual void f() { cout << "Base::f" << endl; } virtual void g() { cout << "Base::g" << endl; } virtual void h() { cout << "Base::h" << endl; } }; 我们可以通过Base 的实例来得到虚函数表。 Code 2: typedef void(*Fun)(void); Base b; Fun pFun = NULL; cout << "虚函数表地址:" <<(int *)*(int*)(&b) << endl; cout << "虚函数表 — 第一个函数地址:" << (int*)*((int*)*(int*)(&b)) << endl; // Invoke the first virtual function pFun = (Fun)*((int*)*(int*)(&b)); pFun(); 实际运行经果如下:(Windows XP+VC6.0) 虚函数表地址:0x00425030 虚函数表 — 第一个函数地址:0040100F Base::f 通过Code 2 看到,可以通过强行把&b 转成int *,取得虚函数表的地址,然后,再次取址就可以得到第一个虚函数的地址了,也就是Base::f(),这在上面的程序中得到了验证(把int* 强制转成了函数指针)。如此就可以知道如果要调用Base::g()和 Base::h(),其代码如下: Code 3: (Fun)*((int*)*(int*)(&b)+0); // Base::f() (Fun)*((int*)*(int*)(&b)+1); // Base::g() (Fun)*((int*)*(int*)(&b)+2); // Base::h() 通过类实例的偏移地址得到函数表地址,...