zoukankan      html  css  js  c++  java
  • 总结C++中取成员函数地址的几种方法

      这里, 我整理了4种C++中取成员函数地址的方法, 第1,2,4种整理于网上的方法, 第3种cdecl_cast是我自己想到的.
      其中, 第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;
    }

     


    女孩不哭 @ 2013-08-17 10:47:34 @ http://www.cnblogs.com/nbsofer

  • 相关阅读:
    吴裕雄--天生自然C语言开发:共同体
    吴裕雄--天生自然C语言开发:结构体
    吴裕雄--天生自然C语言开发:字符串
    吴裕雄--天生自然C语言开发:函数指针
    吴裕雄--天生自然C语言开发:指针
    吴裕雄--天生自然C语言开发:enum(枚举)
    100个容器周边项目,点亮你的容器集群技能树
    论云时代最经济的APM工具的姿势
    “弹性裸金属服务器”到底有那些特性?
    弹性裸金属服务器服务于市场的技术概要分析
  • 原文地址:https://www.cnblogs.com/memset/p/get_member_function_address_cpp.html
Copyright © 2011-2022 走看看