C++虚函数表解析 [二]

2014-11-24 12:39:00 · 作者: · 浏览: 1

虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。在这个表中,主要是一个类的虚函数的地址,这张表解决了继承、覆盖的问题,其内容真实反映了实际函数。这样,在有虚函数的类的实例中虚函数表被分配在实例的内存中,所以,当用父类的指针从操作一个子类的时候,这张虚函数表就显得尤为重要了,它就像一张地图,指明了实际所应该调用的函数。

C++的标准规格说明书中写道,编译器必须保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证正确取到虚函数的偏移量)。这意味着通过对象实例的地址可以得到虚函数表,然后可以遍历其中的函数指针,并调用相应的函数了。请看下面的代码

class Base{

public:

virtual void fun1(){cout<<"Base::fun1"<

virtual void fun2(){cout<<"Base::fun2"<

virtual void fun3(){cout<<"Base::fun3"<

private:

int num1;

int num2;

};

typedef void(*Fun)(void);

int main(int argc, char* argv[])

{

Base b;

Fun pFun;

pFun=(Fun)*((int*)*(int*)(&b)+0);

pFun();

pFun=(Fun)*((int*)*(int*)(&b)+1);

pFun();

pFun=(Fun)*((int*)*(int*)(&b)+2);

pFun();

return 0;

}

上面程序的执行结果如下:

Base::fun1

Base::fun2

Base::fun3

可以看到通过函数指针pFun的调用,分别执行了对象b的3个虚函数。通过这个示例发现,可以强行把&b转成int*,取得虚函数表的地址,然后再次取址就可以得到第一个虚函数的地址了,也就是Base::fun1()。如果调用Base::fun2()和Base::fun3(),只需要把&b先加上数组元素的偏移,后面的步骤类似。

程序中Base对象b的内存结构图,如下图所示:

\

摘自:日新为道的专栏