先还是看看下面的代码:
#include <iostream>
using namespace std;
class A
{
private:
int a;
int b;
public:
virtual void vfun0()
{
cout << "A::vfun0" << endl;
}
virtual void vfun1()
{
cout << "A::vfun1" << endl;
}
};
// 定义一个函数指针类型fun,此类函数没有参数,返回类型为void
typedef void (*fun)();
fun getVirtualFunction(A* obj, unsigned long offset)
{
// 1. obj就是类A的对象地址,而vfptr总是在一个对象内存布局的最前面,因此obj其实也就是vfptr的开始;
// 2. 在32-bit的操作系统中,地址空间也是32-bit的,我们知道long是4Bytes,因此(unsigned long*)obj就是vfptr
// 指针(即包括obj及其后面3个Bytes的内容,unsigned long*从本质上说,就是限定包括obj及其后面3个Bytes的
// 内容作为vfptr指针);
// 3. *(unsigned long*)obj,就是vfptr指针中的内容,其中前4Bytes也就是virtual table的起始地址;
// 4. (unsigned long *)(*(unsigned long*)obj)取得virtual table的4Bytes地址,也就是虚函数表中第一项,它也
// 是一个指针,这个指针指向第一个虚函数的地址,也就是说该指针的内容为第一个虚函数的指针;如果offset = 1,
// 那么(unsigned long *)(*(unsigned long*)obj) + offset就是虚函数表中第二项,它是一个指向第二个虚函数地
// 址的指针,依此类推;
unsigned long* vtbl = (unsigned long *)(*(unsigned long*)obj) + offset;
// 5. 承4,如果vtbl是虚函数表中第一项,那么*(vtbl)就是第一个虚函数的指针,通过(fun)转化成为一个无参数,返回
// 值类型为void的函数指针,以此类推。
fun p = (fun) *(vtbl);
return p;
}
int main(void)
{
A a;
cout << "Size of class A = " << sizeof(a) << endl;
cout << &a << endl;
getVirtualFunction(&a, 0)();
getVirtualFunction(&a, 1)();
return 0;
}
运行结果:

我们可以看到,通过
getVirtualFunction(&a, 0)();
getVirtualFunction(&a, 1)();
成功地调用了class A中的两个虚函数vfun0和vfun1。getVirtualFunction(&a, 0)和getVirtualFunction(&a, 1)分别就是vfun0和vfun1的函数指针。
http://patmusing.blog.163.com/blog/static/1358349602010419111919799/