【摘要】

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

【正文】

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

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

C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——假设有多层继承或是多重继承的情况下)。 这意味着我们通过对象实例的地址得到这张虚函数表。然后就能够遍历当中函数指针,并调用对应的函数。

【代码演示样例】

#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; }

};

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

推荐阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。