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