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