学习C++虚函数时的指针问题
在自学C++时看过许多博文,看到一篇博文中有如下:
class Base {
public:
virtual void f() { cout << "Base::f" << endl; }
virtual void g() { cout << "Base::g" << endl; }
virtual void h() { cout << "Base::h" << endl; }
};
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();
自己想了却是如何也想不明白,我觉得 (int*)(&b) 应该是指向虚函数表的指针本身的地址,*(int*)(&b)是虚函数表的地址,(int*)*(int*)(&b)也是虚函数表的地址,*(int*)*(int*)(&b)是第一个函数地址,可是自己用vs测试时发现 *(int*)(&b)与(int*)*(int*)(&b)输出不同,而&b与(int*)(&b)却是相同的,
还有pFun()是具体如何调用了class Base 中f()函数的.
求大牛帮忙解答,越详细越好!!
[解决办法]
首先一点,vptr在对象模型的头还是尾,标准没有规定。因此,不同的compiler,这可能不同。据说,vc是放在头的。所以这个程序可以假设是在vc编译器下。
&b与(int*)(&b)肯定相同,都是vptr的地址,*(int*)(&b)就是vptr的内容,就是vtable地址。在有些compiler下,vtable的第一条是class的type info,但这里显然不是——可能是vc编译器的问题(vc的编译器就是诡异)。我们认为vtable的第一项就是第一个virtual function的地址,为了方便,设:
vptr = *(int*)(&b)
(int*)*(int*)(&b) = (int*)vptr
把vptr的内容转换成一个int*,可以看作一个int数组,就是vtable本身,即:
int vtable[M];
*(int*)vptr => *vtable => vtable[0]
也就是第一个virtual function的地址,后边把它转成了Fun来使用。