这里, 我整理了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+]
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 = ; asm_cast(p4,A::fn); cout<<p1<<endl<<p2<<endl<<p3<<endl<<p4<<endl; return ;
}

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

总结C++中取成员函数地址的几种方法的更多相关文章

  1. 【转】总结C++中取成员函数地址的几种方法

    转自:“http://www.cnblogs.com/nbsofer/p/get_member_function_address_cpp.html” 这里, 我整理了4种C++中取成员函数地址的方法, ...

  2. Java中取小数点后两位(四种方法)

    摘自http://irobot.iteye.com/blog/285537 Java中取小数点后两位(四种方法)   一 Long是长整型,怎么有小数,是double吧     java.text.D ...

  3. 驱动中获取PsActiveProcessHead变量地址的五种方法也可以获取KdpDebuggerDataListHead

    PsActiveProcessHead的定义: 在windows系统中,所有的活动进程都是连在一起的,构成一个双链表,表头是全局变量PsActiveProcessHead,当一个进程被创建时,其Act ...

  4. 介绍了如何取成员函数的地址以及调用该地址:C++

    摘要:介绍了如何取成员函数的地址以及调用该地址. 关键字:C++成员函数 this指针 调用约定 一.成员函数指针的用法 在C++中,成员函数的指针是个比较特殊的东西.对普通的函数指针来说,可以视为一 ...

  5. 直接调用类成员函数地址(用汇编取类成员函数的地址,各VS版本还有所不同)

    在C++中,成员函数的指针是个比较特殊的东西.对普通的函数指针来说,可以视为一个地址,在需要的时候可以任意转换并直接调用.但对成员函数来说,常规类型转换是通不过编译的,调用的时候也必须采用特殊的语法. ...

  6. C++ 获取类成员函数地址方法 浅析

    C语言中可以用函数地址直接调用函数:   void print ()   {   printf ("function print");   }   typdef void (*fu ...

  7. c++使用map保存成员函数地址

    note 本基于c++11介绍一种使用map保存成员函数地址 可避免使用 if 和 switch 配置灵活 方便, 代码维护效率高 结果: 范例开始 头文件包含 #include <iostre ...

  8. C++(十六) — 类中引用成员函数、命名空间的使用

    1.为什么类中引用成员函数? 类将属性和方法做了封装.类是一种数据类型,也就是:固定大小内存块的别名. 类的定义是一个抽象的概念,定义时不分配内存,当用类定义对象时,才分配一个固定大小的内存块. 此时 ...

  9. 【Java.Regex】使用正则表达式查找一个Java类中的成员函数

    代码: import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; imp ...

随机推荐

  1. 安全系列之二:OAuth2.0 开放授权协议

    本文提取出OAuth2.0规范RFC6749的主要内容,部分内容从文档复制出来,给大家讲讲第三方授权背后的故事. 先是举个知乎的QQ登录授权的例子,然后讲四种授权方式,两种令牌,接着是看看协议流程,分 ...

  2. Windows平台配置Appium+Java环境

    1) 安装JDK 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 安装 ...

  3. 项目管理实践 -- 健身小管家(Fitness housekeeper)的管理

      最近在网上看到一篇文章<王石:我每天都强迫自己做的一件事>,[http://blog.sina.com.cn/s/blog_4dfc1c330102v0d0.html] 原始链接不详. ...

  4. SQL编程之生日问题

    在学习MySQL的时候,一个较为经典的SQL编程题目就是生日问题,已知某个用户的出生日期和当前日期,计算他近期的生日. 一般须要考虑两个问题 闰年2月是29天 今年的生日是否过完 比如:某人的生日是1 ...

  5. inux上iptables防火墙的基本应用教程

    iptables是Linux上常用的防火墙软件,下面vps侦探给大家说一下iptables的安装.清除iptables规则.iptables只开放指定端口.iptables屏蔽指定ip.ip段及解封. ...

  6. android 当目录路径从n层按back键退回到n-19层的时候,file manager自己主动退出

    当目录路径从n层按back键退回到n-19层的时候,file manager自己主动退出,比方在63层按back 键退回到44层的时候,file manager自己主动退出.   1.FileMana ...

  7. protobuf-net-data

    protobuf-net http://www.codeproject.com/Articles/642677/Protobuf-net-the-unofficial-manual https://g ...

  8. UiAutomator源码分析之UiAutomatorBridge框架

    上一篇文章<UIAutomator源码分析之启动和运行>我们描述了uitautomator从命令行运行到加载测试用例运行测试的整个流程,过程中我们也描述了UiAutomatorBridge ...

  9. .net4.5的弱事件

    .net4.5的弱事件 没有伟大的愿望,就没有伟大的天才--Aaronyang的博客(www.ayjs.net)-www.8mi.me 1. 事件-我的讲法 老师常告诉我,事件是特殊的委托,为委托提供 ...

  10. 织梦不仅是链接到其他调用next

    //打开系统文件织梦 /include/arc.archives.class.php 找到GetPreNext函数 function GetPreNext($gtype='') { $rs = ''; ...