直接调用类成员函数地址
2010-07-25 20:45:42 来源:WEB开发网二、取成员函数的地址
当然,引用某位大师的话:"在windows中,我们总是有办法的"。同样,在C++中,我们也总是有办法的。这个问题,解决办法已经存在了多年,并且广为使用(在MFC中就使用了)。一般有两个方法,一是使用内嵌的汇编语言直接取函数地址,二是使用union类型来逃避C++的类型转换检测。两种方法都是利用了某种机制逃避C++的类型转换检测,为什么C++编译器干脆不直接放开这个限制,一切让程序员自己作主呢?当然是有原因的,因为类成员函数和普通函数还是有区别的,允许转换后,很容易出错,这个在后面会有详细的说明。现在先看看取类成员函数地址的两种方法:
第一种方法:
template
void GetMemberFuncAddr_VC6(ToType& addr,FromType f)
{
union
{
FromType _f;
ToType _t;
}ut;
ut._f = f;
addr = ut._t;
}
这样使用:
DWORD dwAddrPtr;
GetMemberFuncAddr_VC6(dwAddrPtr,&tt::foo);
为什么使用模版? 呵呵,如果不使用模版,第二个参数该怎么些,写成函数指针且不说太繁琐,关键是没有通用性,每个成员函数都要单独写一个转换函数。
第二种方法:
#define GetMemberFuncAddr_VC8(FuncAddr,FuncType)
这样使用:
{
__asm
{
mov eax,offset FuncType
};
__asm
{
mov FuncAddr, eax
};
}
DWORD dwAddrPtr;
GetMemberFuncAddr_VC8(dwAddrPtr,&tt::foo);
本来是想写成一个模版函数的,可惜虽然通过了编译,却不能正确运行。估计在汇编代码中使用模版参数不太管用,用offset取偏移量直接就得0。
上面的宏是可以正确运行的,并且还有一个额外的好处,就是可以直接取私有成员函数的地址(大概在asm括号中,编译器不再检查代码的可访问性)。不过缺点是它在vc6下是无法通过编译的,只能在VC8下使用。
更多精彩
赞助商链接