小弟我真的通过虚函数表,调用了小弟我想要的函数吗?这上懵了

我真的通过虚函数表,调用了我想要的函数吗?这下懵了。
本帖最后由 ngbbxt 于 2013-01-24 11:37:33 编辑
经过下面代码,为什么输出来的两个this,不相等,懵了。




class Base {
public:
Base()
{
cout<<"Base()::this  "<<this<<endl;
}
virtual void f()
{
cout<< "Base::f()  this  "<<this<<endl;
}
};


Base b;
typedef void(*Fun)(void);
Fun pFun = (Fun)*((int*)*(int*)(&b));//这里是通过访问虚表,来获取目的函数。
pFun();




------解决方案--------------------
楼主你以_cdecl的方式调用成员函数,没有处理ECX寄存器,那自然就不会保存this指针,所以不仅是this,如果有其他成员变量也不会正确的。
所以在_cdecl的情况下请手动对ECX寄存器赋值

Base b;
typedef void(*Fun)(void);
Fun pFun = (Fun)*((int*)*(int*)(&b));//这里是通过访问虚表,来获取目的函数。
__asm
{
lea ECX,[b]
}
pFun();


另外你还可以使用_fastcall的方式,通过堆栈而非ECX得到this

Base b;
typedef void(__fastcall *Fun)(Base* b);
Fun pFun = (Fun)*((int*)*(int*)(&b));//这里是通过访问虚表,来获取目的函数。
pFun(&b);

------解决方案--------------------
使用__fastcall调用thiscall约定的函数,主要是因为他们都是从右向左入栈的(9楼说的从右向左就是指的这个,不是ECX和EDX寄存器),而且正好可以利用其使用ECX寄存器传参的特点,存储this指针。
至于EDX,则用NULL占位,如果第二个参数直接传2,pFun 不会push这个2,会放进EDX,到函数f中则EDX为2,但是thiscall约定的函数是不会从EDX拿这个参数的,它只关心堆栈,所以把2作为第三个参数传入,那么pFun就push了一个2,那么对于f函数来说就只有一个参数,从堆栈中得到就是2了