读书人

学习C++虚函数时的指针有关问题

发布时间: 2013-01-02 13:08:44 作者: rapoo

学习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来使用。

读书人网 >C++

热点推荐