讲解虚函数表的好文章:C++虚函数表解析---陈皓:http://blog.csdn.net/haoel/article/details/1948051/
前言:本篇文章是对《C++虚函数表解析》的注解,感谢陈大牛对虚函数表的详细介绍,确实吊。让我们go吧。
学习虚函数表前你应该知道虚函数是什么了吧!明白虚函数是做什么用的了吧!
1、虚函数表是什么?虚函数表是干什么用的?
虚函数表(Virtual method table,来自维基百科)是被编程语言用来实现动态调度的机制(is a mechanism used in a programming language to supportdynamic dispatch (or run-time method binding))。
虚函数表的作用:当一个类定义了一个虚函数,大多数编译器会为这个类增加一个隐藏的成员变量(一个指针),这个成员变量指向一个由虚函数地址(也就是指向这些虚函数的指针)组成的数组。这个数组就是虚函数表(VMT or Vtable)。虚函数表中存储了为对象进行声明的虚函数的地址。在运行时,这些指针会被设置为指向正确的虚函数。(Whenever a class defines a virtual function (or method), most compilers add a hidden member variable to the class which points to an array of pointers to (virtual) functions called the virtual method table (VMT or Vtable). At runtime these pointers will be set to point to the right function)。
虚函数表中存放的是这个类的虚函数的地址表,你也可以理解成存放的是一个指针,这个指针指向的就是虚函数的地址;
2、《C++虚函数表解析》的第一个例子分析
看明白第一个例子,对读懂这篇文章后面的内容就容易多了;来看第一个例子,代码如下:
#include <iostream> using namespace std; class Base { public: virtual void f() { cout << "Base::f" << endl; } virtual void g() { cout << "Base::g" << endl; } virtual void h() { cout << "Base::h" << endl; } }; int main() { typedef void(*Fun)(void); Base b; Fun pFun = NULL; cout << "虚函数表地址:" << (int*)(&b) << endl; cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&b) << endl; // Invoke the first virtual function pFun = (Fun)*((int*)*(int*)(&b)); pFun(); return 0; }
分析:类Base中定义了4个虚函数,在main函数中定义Base类对象b的时候,生成一个虚函数表。注意,申请的这个虚函数表的指针是存在于对象实例中最前面的位置。这就是为什么语句(int*)(&b)得到的就是虚函数表的地址;这样说能明白吗?美眉。(int*)(&b)是什么意思呢,从右边像左看,“&b”是取地址,取的是虚函数表的地址,(int*)是强制类型转换,是将&b强制转换成int*的形式,然后再输出,这样说可以吗。
紧接着看(int*)*(int*)(&b) 是什么意思,这里我们主要分析(int*)和(int*)之间的这个“*”的意思,&b代表地址,*&b代表的肯定就是取这个地址指向的内容了。也就是说,取虚函数表中的第一个内存中存放的内容。取到的就是指向第一个虚函数的地址;
pFun = (Fun)*((int*)*(int*)(&b));这句话的意思函数指针pFun指向第一个虚函数;
pFun();就相当于b.f();
小弟不才,表达能力不好,也在锻炼,讲的不通地方请大家指正,第一时间会做修改。
明白这些,读明白《C++虚函数表解析》就容易多了。