C++虚函数表总览

2013年4月17日 由 Creater 留言 »

阅读陈皓的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 ‎

广告位

发表评论

你必须 登陆 方可发表评论.