虚函数的虚函数表实现机制
#include <stdio.h>
#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 << "虚函数表地址:" << &b<< endl;
cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&b) << endl;
pFun = (Fun)*((int*)*(int*)(&b));
pFun();
return 0;
}
pFun = (Fun)*((int*)*(int*)(&b));
上面这种写法,是假定vptr放在对象模型的开头,因为对于一个类如果有成员变量,那么
这个虚拟指针(vptr)可以放在末尾,或是其它的地方,标准并没有对此有规定,因此这种说法不一定正确。
但是,
我们这儿纯属讨论使用,假vptr定放在对象模型的开头。
这样&b,这就是vptr的地址(放在开头),然后这个地址转换成(int*),再对它进行解引用*,
也就是*(int*)(&b),这个解引用是什么呢?
我们知道vptr指向vtable,而vtable是存放虚函数的地址。对vptr的解引用(*),实际上
就是访问vtable,(vtable可以存放很多函数的地址,为求简单,现在我们只考虑一个),
然后,我们再把这个vtable指针转化成(int*),然后再解引用,前面我们已经说过,vtable存放的是函数的指针,当对vtable进行解引用的时候,实际上就是指向这个函数了。