总结C++中取成员函数地址的几种方法
2016-06-04 16:24
555 查看
这里, 我整理了4种C++中取成员函数地址的方法, 第1,2,4种整理于网上的方法, 第3种cdecl_cast是我自己想到的.
其中, 第4种(汇编)的方法不能在VC6上编译通过. 推荐使用第1,2种方法(pointer_cast 和 union_cast).
至于:为什么要取成员函数的地址? 因为可以通过一定的手段 让成员函数作为回调函数 , 而不再使用全局的静态函数.
天气热,话不多说, 使用方法见最后.
方法1: pointer_cast - 通过静态转换
其实, 我并不明白这个方法为什么成功了, 而且要使用两个static_cast, 一个不行. 而且函数里面使用的&src,
但我传入参数的时候还需要以&ClassName::MemFunc的形式, 不然就是错误的, 为什么?
方法2: union_cast - 通过联合体的共享储存机制
这种方法是最常规, 也是最好理解的一种方法了, 巧妙地利用了联合体的优点. 当然, 模板的使用恰到好处. 同时,传入参数时注意数据类型大小一致.
方法3: cdecl_cast - 通过C语言的可变参数不检测参数类型
注:在Windows上函数返回值通过eax返回, 所以只需要这么两条汇编语句就行了. 只用于32位平台, 若用于64位, 需要修改一下寄存器.
虽然使用了三个点形式的参数, 但是参数只需传入一个.
方法4: asm_cast - 通过汇编的offset语句取成员函数偏移得到地址
注:这个方法也比较巧妙, 不过貌似在VC6上编译不过. VS2012没问题.
使用方法及测试代码:
其中, 第4种(汇编)的方法不能在VC6上编译通过. 推荐使用第1,2种方法(pointer_cast 和 union_cast).
至于:为什么要取成员函数的地址? 因为可以通过一定的手段 让成员函数作为回调函数 , 而不再使用全局的静态函数.
天气热,话不多说, 使用方法见最后.
方法1: pointer_cast - 通过静态转换
template<typename dst_type,typename src_type> dst_type pointer_cast(src_type src) { return *static_cast<dst_type*>(static_cast<void*>(&src)); }
其实, 我并不明白这个方法为什么成功了, 而且要使用两个static_cast, 一个不行. 而且函数里面使用的&src,
但我传入参数的时候还需要以&ClassName::MemFunc的形式, 不然就是错误的, 为什么?
方法2: union_cast - 通过联合体的共享储存机制
template<typename dst_type,typename src_type> dst_type union_cast(src_type src) { union{ src_type s; dst_type d; }u; u.s = src; return u.d; }
这种方法是最常规, 也是最好理解的一种方法了, 巧妙地利用了联合体的优点. 当然, 模板的使用恰到好处. 同时,传入参数时注意数据类型大小一致.
方法3: cdecl_cast - 通过C语言的可变参数不检测参数类型
__declspec(naked) void* __cdecl cdecl_cast(...) { __asm{ mov eax,dword ptr[esp+4] ret } }
注:在Windows上函数返回值通过eax返回, 所以只需要这么两条汇编语句就行了. 只用于32位平台, 若用于64位, 需要修改一下寄存器.
虽然使用了三个点形式的参数, 但是参数只需传入一个.
方法4: asm_cast - 通过汇编的offset语句取成员函数偏移得到地址
#define asm_cast(var,addr) \ { \ __asm{ \ mov var,offset addr \ } \ }
注:这个方法也比较巧妙, 不过貌似在VC6上编译不过. VS2012没问题.
使用方法及测试代码:
#include <iostream> using namespace std; class A { public: void fn(){} }; int main(void) { void* p1 = pointer_cast<void*>(&A::fn); void* p2 = union_cast<void*>(&A::fn); void* p3 = cdecl_cast(&A::fn); void* p4 = 0; asm_cast(p4,A::fn); cout<<p1<<endl<<p2<<endl<<p3<<endl<<p4<<endl; return 0; }
相关文章推荐
- C++为什么用模板类,为什么用泛型?
- c++ 中求反正切的函数atan和atan2的差别?
- C++sqrt()函数与sqrtf()函数有什么区别?
- 第10周 C语言及程序设计提高例程-40 小小型应用系统开发指导(四)
- How to Marshal a C++ Class
- c++实验7-最大公约数与最小公倍数
- C++ Primer 面向对象编程 15.2 基类和派生类 virtual
- LeetCode 90 Subsets II--In C++
- 友元类与友元函数的继承与传递问题
- c++实验7-特殊三位数
- C语言课程设计报告
- C++作业7-函数复习
- VS VC++ 设置版本号
- (C++) 作用域和链接
- 面试题总结之C/C++
- Sublime text3C/C++ 编译环境设置
- C++精髓之多态性与虚函数
- C语言通信处理函数
- c++关于函数的按值传递和按址传递
- C++ 实现一个二进与文本形式存储的小型数据库(未完成)