• 欢迎浏览“String me = Creater\忠实的资深Linux玩家;”,请文明浏览,理性发言,有侵犯你的权益请邮件我(creater@vip.qq.com).
  • 把任何的失败都当作一次尝试,不要自卑;把所有的成功都想成是一种幸运,不要自傲。
  •    6年前 (2013-04-17)  C++ |   2 条评论  10 
    文章评分 0 次,平均分 0.0

    阅读陈皓的C++虚函数表解析后,我来总结一下,加深理解。

    虚函数是实现多态的基础,每个对象都维持着一个虚函数表(VTABLE),这个表分布在哪里?在对象所占内存空间的哪部分?

    得来先看看内存布局,再来说下面的代码,已知下面代码中Base类的对象b。

    o_vtable1

    b是一个对象的名字,可以通过该对象名来访问对象;

    1.&b是该对象在内存中的起始地址,可以通过该地址来访问对象;

    2.(int*)&b,因为32位操作系统,指针是32位的,所以这里转换下;

    3.*((int*)&b),对&b开始的地址里的内容作为地址来取内容,这说明对象的头4个字节里放的是虚函数表的地址,虚函数放在哪里?那就是放在该地址指向的内存区;

    4.(int*)*(int*)(&b),因为虚函数表也是存放指针(函数指针),也是32位,所以也转换一下。

    代码:

    #include
    #include
    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 pFunc = NULL;
    	cout<<"虚函数表地址"<<(int*)(&b)<<endl;
    	cout<<"虚函数表中第一个函数地址"<<(int*)*(int*)(&b)<<endl;
    	pFunc = (Fun)*((int*)*(int*)(&b));
    	pFunc();
    	return 0;
    }

    输出为:
    虚函数表地址0xbf9eb9e8
    虚函数表中第一个函数地址0x8048960
    Base::f

    至此,(int*)(&b)获取到了对象内存区的头4个字节作为虚函数表的地址;(int*)*(int*)(&b)则作为了第一个虚函数的地址。有了这些知识,很轻松就知道:

    cout<<"虚函数表地址"<<(int*)(&b)<<endl;
    cout<<"虚函数表中第1个函数地址"<<(int*)*(int*)(&b)<<endl;
    cout<<"虚函数表中第2个函数地址"<<((int*)*(int*)(&b)) + 1<<endl;
    cout<<"虚函数表中第3个函数地址"<<((int*)*(int*)(&b)) + 2<<endl;
    
    虚函数表地址0xbfe02a98
    虚函数表中第1个函数地址0x8048a28
    虚函数表中第2个函数地址0x8048a2c
    虚函数表中第3个函数地址0x8048a30
    

    下一节:http://unix8.net/home.php/c虚函数表一般继承.html ‎

     

    除特别注明外,本站所有文章均为String me = "Creater\忠实的资深Linux玩家";原创,转载请注明出处来自http://unix8.net/home.php/742.html

    关于

    发表评论

    暂无评论

    切换注册

    登录

    忘记密码 ?

    切换登录

    注册

    扫一扫二维码分享