现在的位置: 首页 > 综合 > 正文

C++虚函数表的测试

2013年10月08日 ⁄ 综合 ⁄ 共 4961字 ⁄ 字号 评论关闭
/*
goal, C++虚函数表的测试,测试了一部分,其他情况以后有机会再学习了。
date, 2013-3-7

http://blog.csdn.net/shunqiziranhao007/article/details/8646489

*/
#include <iostream>
using std::cout; using std::endl;

typedef void(*voidFun)();

// 一个空的类,看看有什么信息可以挖掘,可以拿来和其他情况对比的。
class A1 {};

// 拥有1个非虚函数的类
class A2
{
public:
	void f()
	{
		cout << "A2::f()" << endl;
	}
};

// 拥有1个虚函数的类
class A3
{
public:
	virtual void f()
	{
		cout << "A3::f()" << endl;
	}
};

// 拥有2个虚函数的类
class A4
{
public:
	virtual void f2()
	{
		cout << "A4::f2()" << endl;
	}
	
	virtual void f1()
	{
		cout << "A4::f1()" << endl;
	}
};

// 单继承,不覆盖基类虚函数
class A5: public A3
{
public:
	virtual void g()
	{
		cout << "A5::g()" << endl;
	}
};

// 单继承,不覆盖基类虚函数,3级
class A51: public A5
{
public:
	virtual void h()
	{
		cout << "A51::h()" << endl;
	}
};

// 单继承,覆盖基类虚函数
class A6: public A3
{
public:
	virtual void g()
	{
		cout << "A6::g()" << endl;
	}
	
	virtual void f()
	{
		cout << "A6::f()" << endl;
	}
};

// 多继承,不覆盖基类虚函数
class A7: public A3, public A4
{
public:
	virtual void g1()
	{
		cout << "A7::g1()" << endl;
	}
	
	virtual void g()
	{
		cout << "A7::g()" << endl;
	}
};

// 多继承,覆盖基类虚函数
class A8: public A3, public A4
{
public:
	virtual void f1()
	{
		cout << "A8::f1()" << endl;
	}
	
	virtual void f()
	{
		cout << "A8::f()" << endl;
	}
	
	virtual void g()
	{
		cout << "A8::g()" << endl;
	}
};

int main()
{
	// 类的虚函数表的表的指针,它指向一个虚函数表的表,表中元素指向虚函数表。
	// 虚函数表由类的虚函数地址组成。
	int **pVTable;
	
	// 空类的情况
	A1 a1;
	// 虽然什么也没有,但是空类对象的大小是1,为什么不是0,是1而不是2其他的呢?
	// 具体我还不清楚,对于空类对象数组a[10],空类有了空间就可以区分a[0],a[1]。
	cout << "空类A1的大小:" << sizeof(a1) << endl;
	cout << "A1的虚函数表地址: " << (int *)(&a1) << endl;
	cout << endl;
	
	// 拥有一个非虚函数的类
	A2 a2;
	// 由于没有数据成员,所以大小还是1,其成员函数则放在其他地方。
	cout << "拥有一个非虚函数的类A2的大小:" << sizeof(a2) << endl;
	cout << "A2的虚函数表地址: " << (int *)(&a2) << endl;
	cout << "A2的虚函数表中第1个函数的地址: " 
		<< (int *)*( (int *)(&a2) ) << endl;
	// 由于没有虚函数,所以这个类就没有虚函数表,所以下面那样使用就出错(取了未知
	// 地址处的值)。
	// ((voidFun)*((int *)*( (int *)(&a2) )))();
	cout << endl;

	// 拥有1个虚成员函数的类
	A3 a3;
	// 由于有了虚成员函数,就会增加1个虚函数表地址成员,大小是4了。
	cout << "拥有1个虚函数的类A3的大小:" << sizeof(a3) << endl;
	cout << "A3的虚函数表地址: " << (int *)(&a3) << endl;
	pVTable = (int **)&a3;
	cout << "A3的虚函数表中第1个函数的地址: " << &pVTable[0][0] << endl;
	((voidFun)pVTable[0][0])();
	// cout << "A3的虚函数表中第2个函数的地址: " << &pVTable[0][1] << endl;
	// 这样调用失败。
	// ((voidFun)pVTable[0][1])();
	cout << "A3的虚函数表的最后一个元素的内容是:" << pVTable[0][1] << endl;
	// 由上可知,虚函数表的最后一个元素的内容是?怎么不是0呢?
	cout << endl;
	
	// 拥有2个虚成员函数的类
	A4 a4;
	// 大小还是4
	cout << "拥有2个虚函数的类A4的大小:" << sizeof(a4) << endl;
	cout << "A4的虚函数表地址: " << (int *)(&a4) << endl;
	pVTable = (int **)&a4;
	cout << "A4的虚函数表中第1个函数的地址: " 
		<< &pVTable[0][0] << endl;
	((voidFun)pVTable[0][0])();
	cout << "A4的虚函数表中第2个函数的地址: " 
		<< &pVTable[0][1] << endl;
	((voidFun)pVTable[0][1])();
	cout << "A4的虚函数表的最后一个元素的内容是:" << pVTable[0][2] << endl;
	// 由上发现虚函数真的是一张表格啊,而且是根据类中的虚函数声明顺序进行放置。
	cout << endl;
	
	// 单继承,不覆盖基类虚函数
	A5 a5;
	cout << "单继承,不覆盖基类虚函数的类A5的大小:" << sizeof(a5) << endl;
	cout << "A5的虚函数表地址: " << (int *)(&a5) << endl;
	pVTable = (int **)&a5;
	cout << "A5的虚函数表中第1个函数的地址: " 
		<< &pVTable[0][0] << endl;
	((voidFun)pVTable[0][0])();
	cout << "A5的虚函数表中第2个函数的地址: " 
		<< &pVTable[0][1] << endl;
	((voidFun)pVTable[0][1])();
	cout << "A5的虚函数表的最后一个元素的内容是:" << pVTable[0][2] << endl;
	// 由上发现在派生类的虚函数表中,基类的虚函数在派生类的虚函数前面
	cout << endl;
	
	// 单继承3级,不覆盖基类虚函数
	A51 a51;
	cout << "单继承3级,不覆盖基类虚函数的类A51的大小:" << sizeof(a51) << endl;
	cout << "A51的虚函数表地址: " << (int *)(&a51) << endl;
	pVTable = (int **)&a51;
	cout << "A51的虚函数表中第1个函数的地址: " << &pVTable[0][0] << endl;
	((voidFun)pVTable[0][0])();
	cout << "A51的虚函数表中第2个函数的地址: " << &pVTable[0][1] << endl;
	((voidFun)pVTable[0][1])();
	cout << "A51的虚函数表中第3个函数的地址: " << &pVTable[0][2] << endl;
	((voidFun)pVTable[0][2])();
	cout << "A51的虚函数表的最后一个元素的内容是:" << pVTable[0][3] << endl;
	// 由上发现在派生类的虚函数表中,基类的虚函数在派生类的虚函数前面
	cout << endl;
	
	// 单继承,覆盖基类虚函数
	A6 a6;
	cout << "单继承,覆盖基类虚函数的类A6的大小:" << sizeof(a6) << endl;
	cout << "A6的虚函数表地址: " << (int *)(&a6) << endl;
	pVTable = (int **)&a6;
	cout << "A6的虚函数表中第1个函数的地址: " 
		<< &pVTable[0][0] << endl;
	((voidFun)pVTable[0][0])();
	cout << "A6的虚函数表中第2个函数的地址: " 
		<< &pVTable[0][1] << endl;
	((voidFun)pVTable[0][1])();
	cout << "A6的虚函数表的最后一个元素的内容是:" << pVTable[0][2] << endl;
	// 由上发现派生类覆盖基类的虚函数取代了基类该虚函数的位置
	cout << endl;
	
	// 多继承,不覆盖基类虚函数
	A7 a7;
	// 由于继承了2个类,所以有2个虚函数表,所以大小是8了。
	cout << "多继承,不覆盖基类虚函数的类A7的大小:" << sizeof(a7) << endl;
	cout << "A7的虚函数表地址: " << (int *)(&a7) << endl;
	pVTable = (int **)&a7;
	cout << "A7的虚函数表1中第1个函数的地址: " << &pVTable[0][0] << endl;
	((voidFun)pVTable[0][0])();
	cout << "A7的虚函数表1中第2个函数的地址: " << &pVTable[0][1] << endl;
	((voidFun)pVTable[0][1])();
	cout << "A7的虚函数表1中第3个函数的地址: " << &pVTable[0][2] << endl;
	((voidFun)pVTable[0][2])();
	cout << "A7的虚函数表1的最后一个元素的内容是:" << pVTable[0][3] << endl;
	
	cout << "A7的虚函数表2中第1个函数的地址: " << &pVTable[1][0] << endl;
	((voidFun)pVTable[1][0])();
	cout << "A7的虚函数表2中第2个函数的地址: " << &pVTable[1][1] << endl;
	((voidFun)pVTable[1][1])();
	cout << "A7的虚函数表2的最后一个元素的内容是:" << pVTable[1][2] << endl;
	// 由上发现派生类继承了几个有虚函数的类,就有几个虚函数表。
	// 表的顺序与它继承的声明一致。
	// 派生类自己的虚函数放在它的第一个父类对应的虚函数表中。
	cout << endl;

	// 多继承,覆盖基类虚函数
	A8 a8;
	// 由于继承了2个类,所以有2个虚函数表,所以大小是8了。
	cout << "多继承,覆盖基类虚函数的类A8的大小:" << sizeof(a8) << endl;
	cout << "A8的虚函数表地址: " << (int *)(&a8) << endl;
	pVTable = (int **)&a8;
	cout << "A8的虚函数表1中第1个函数的地址: " << &pVTable[0][0] << endl;
	((voidFun)pVTable[0][0])();
	cout << "A8的虚函数表1中第2个函数的地址: " << &pVTable[0][1] << endl;
	((voidFun)pVTable[0][1])();
	cout << "A8的虚函数表1中第3个函数的地址: " << &pVTable[0][2] << endl;
	((voidFun)pVTable[0][2])();
	cout << "A8的虚函数表1的最后一个元素的内容是:" << pVTable[0][3] << endl;
	
	cout << "A8的虚函数表2中第1个函数的地址: " << &pVTable[1][0] << endl;
	((voidFun)pVTable[1][0])();
	cout << "A8的虚函数表2中第2个函数的地址: " << &pVTable[1][1] << endl;
	((voidFun)pVTable[1][1])();
	cout << "A8的虚函数表2的最后一个元素的内容是:" << pVTable[1][2] << endl;
	// 由上发现派生类覆盖基类的虚函数都将放在虚函数表1,按照声明继承的顺序放置。
	cout << endl;

	return 0;
}
/*

不复制效果过来了。
自己根据主程序分析效果。

*/

抱歉!评论已关闭.