zoukankan      html  css  js  c++  java
  • C++ 关于类与对象在虚函数表上唯一性问题 浅析

    【摘要】

    非常多教材上都有介绍到虚指针、虚函数与虚函数表。有的说类对象共享一个虚函数表,有的说,一个类对象拥有一个虚函数表。还有的说,不管用户声明了多少个类对象,可是,这个VTABLE虚函数表仅仅有一个。也有的在说,每一个具有虚函数的类的对象里面都有一个VPTR虚函数指针,这个指针指向VTABLE的首地址,每一个类的对象都有这么一种指针。今天。我们就来解决问题,同一个类的不同对象,是不是拥有“同样”的虚函数表,这个同样是物理上的同样(内存地址)还是逻辑上的同样(数据结构)。本文现详述例如以下。

    【正文】

    虚指针:每一个含有虚方法(虚函数)对象里有虚表指针。指向虚表。

    虚函数表:虚函数表是顺序存放虚函数地址的,虚表是顺序表,表里存放了虚函数的地址。


    C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——假设有多层继承或是多重继承的情况下)。

     这意味着我们通过对象实例的地址得到这张虚函数表。然后就能够遍历当中函数指针,并调用对应的函数。


    【代码演示样例】

    #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; }
     
    };
    typedef void(*Fun)(void);
    
    int main()
    {
    	Fun pFun = NULL;
    	Base obj_1,obj_2;
    	// obj_1 虚函数表 — 第一个函数
    	pFun = (Fun)*((int*)*(int*)(&obj_1));
    	pFun();
    	pFun = (Fun)*(((int*)*(int*)(&obj_1))+1);
    	pFun();
    	// 输出 虚函数表地址 与 虚函数表元素 的值
    	cout << "obj_1 虚函数表地址:" << (int*)(&obj_1) << endl;
    	cout << "obj_2 虚函数表地址:" << (int*)(&obj_2) << endl;
    	cout << "obj_1 虚函数表 — 第一个函数地址:" << (int*)*(int*)(&obj_1) << endl;
    	cout << "obj_2 虚函数表 — 第一个函数地址:" << (int*)*(int*)(&obj_2) << endl;
    	return 0;
    }
    /*
    输出 :
    Base::f      
    Base::g 
    obj_1 虚函数表地址:0018FF40                         
    obj_2 虚函数表地址:0018FF3C                         
    obj_1 虚函数表 — 第一个函数地址:0046F0AC           
    obj_2 虚函数表 — 第一个函数地址:0046F0AC           
    Press any key to continue                                                                                 
    */

    【结论】

    不同对象虚函数表表中元素是相等的。逻辑上是一样的,存放的都是类中虚函数的地址;

    不同对象虚函数表的内存地址是不一样,物理上是不一样的,一个对象是一个新的表。

    【相关推荐】

    详见:C++ 虚函数表解析

    详址:http://blog.csdn.net/haoel/article/details/1948051#comments

  • 相关阅读:
    设置 menu 菜单 监听
    在 flash.net.FileReference 上找不到属性 save,且没有默认值。
    swf获取当前页面的路径
    控制舞台缩放比例
    相对于自身的坐标位移
    tweenmax
    exe文件反编译为源文件
    spring 整合 spring mvc
    springmvc学习第四天
    springmvc学习第三天
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7239095.html
Copyright © 2011-2022 走看看