取虛表的內容

#include <iostream>
#include <typeinfo>

using namespace std;

class CFather
{
public:
	virtual void fun()
	{
		//cout << typeid(*this).name() << " " << "fun()" << endl;
		cout << "fun()" << endl;
	}

	virtual void show()
	{
		cout << "CFather  " << "show()" << endl;
	}
};

class CSon : public CFather
{
public:
	virtual void show()
	{
		cout << "CSon " << "show()" << endl;
	}
};

int main()
{
	CFather * fa = new CSon;
	//取虛表的內容
	// (int *) fa    在 fa 前面加上(int*) 是:將 CFather * 強轉爲(int *)指針,因爲虛表的地址是對象的前四個字節裏面,所以轉換成(int *)指針,就是四個字節
	// *(int*) fa  在(int*)fa前面加上* 是 : 將虛表的地址的前四個字節的內容取出,這就是虛表的地址,*(int*)fa就是虛表的地址
	// (int*)(*(int*)fa) 將虛表的地址強轉爲(int*)類型,這是因爲虛表就是一個數組,每一個數組元素就佔四個字節(32位是四個,64位是8個)
	//                   
	// *((int*)(*(int*)fa) + 0) 獲取虛表數組的第一個元素的內容,就是虛函數列表的第一個虛函數的地址,這裏CFather的第一個虛函數是 void fun()
	//                      
	// *((int*)(*(int*)fa) + 1) 獲取虛表數組的第二個元素的內容呢,就是虛函數列表的第二個函數地址,這裏CFather的第二個虛函數是void fun(),因爲是fa是指向子類的地址,
	//                            第二個虛函數void fun() 在子類中有重寫,所以這裏將是子類的 void fun()函數的地址

	typedef void(*p)(); //typedef 一個函數指針 爲p
	//(p)(*((int*)(*(int*)fa) + 0)) //將虛函數列表裏面的第一個函數地址,強轉爲函數指針
	// 函數指針調用函數,就是在指針後面加小括號 ()
	((p)(*((int*)*(int*)fa + 0)))(); //調用 fun()函數
	((p)(*((int*)(*(int*)fa) + 1)))();//調用 show()函數,注意是子類的show()函數

	//虛表的結尾
	int * p2 = (int*)*((int*)*(int*)fa + 2);//CFather只有兩個虛函數,所以 + 2 就是到了虛函數列表的結尾,然後可以看到pp的內容是0x00000000,這裏我用VS2008並不是這個,是一個隨機的地址,用VS2013是這個
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章