访问基类的私有虚函数 "*((int*)*(int*)(&b)+i)"
#include <iostream>
using namespace std;
class Base
{
virtual void g()
{
cout << "Base::g" << endl;
}
virtual void f()
{
cout << "Base::f" << endl;
}
};
class Derived:public Base
{
void g()
{
cout << "Derived::g" << endl;
}
virtual void h()
{
cout << "Derived::h" << endl;
}
};
typedef void (* Fun)(void);
int main(void)
{
Derived d;
Fun pFun = NULL;
for (int i = 0; i < 3; ++i)
{
pFun = (Fun)*((int *)*(int *)(&d) + i);
pFun();
}
return 0;
}
VS2010环境下运行结果:
Derived::g
Base::f
Derived::h
结论:
1: 应该有假设“指向虚函数表vtable的虚函数表指针vt_ptr位于位于对象内存块的开始处”;
2: (Fun)*((int *)*(int *)(&d) + i): (将指针当做地址)
(&d): 获得对象d的地址addr1,此地址对应整个对象d的内存块;
(int*)(&d): 将Derived类型地址addr1强制转换为int类型地址addr2,此地址对应的内存块即为vt_ptr变量;
*(int*)(&d): 取int类型地址addr2对应内存块中的值,得int类型值val1,该值其实为虚函数表的首地址;
(int*)*(int*)(&d): 将int类型值val1强制转换为int类型地址addr3,该值即为虚函数表vtable的首地址;
((int*)*(int*)(&d)+i): 对int类型地址addr3进行算术加,得到虚函数表中元素i的地址addr_i;
*((int*)*(int*)(&d)+i): 取int类型地址addr_i对应内存块中的值的int类型值val_i,该值其实为虚函数表中元素i中存储的对应的虚函数的指针;
(Fun)*((int *)*(int *)(&d) + i): 将int类型值val_i强制转换为Fun类型地址(指针);
论证:
上述讨论中将指针看做地址,其实指针和地址应该是等效的:
int a = 0xAAAABBBB;
int *b = &a;
对以上两个定义语句,a和b都有自己的内存块,假设对应地址值分别为addr_a和addr_b。
则当执行表达式(int *)*b时,意思是将地址值addr_b对应内存块中存储的值(即为地址值addr_a)所对应的内存块中的值0xAAAABBBB强制转换为int*(即int类型指针,也即int类型地址)。
讨论:
不知这样理解是否正确?