【转】总结C++中取成员函数地址的几种方法
转自:“http://www.cnblogs.com/nbsofer/p/get_member_function_address_cpp.html”
这里, 我整理了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;
}


...
【转】总结C++中取成员函数地址的几种方法的更多相关文章
- 总结C++中取成员函数地址的几种方法
这里, 我整理了4种C++中取成员函数地址的方法, 第1,2,4种整理于网上的方法, 第3种cdecl_cast是我自己想到的. 其中, 第4种(汇编)的方法不能在VC6上编译通过. 推荐使用第1,2 ...
- Java中取小数点后两位(四种方法)
摘自http://irobot.iteye.com/blog/285537 Java中取小数点后两位(四种方法) 一 Long是长整型,怎么有小数,是double吧 java.text.D ...
- 驱动中获取PsActiveProcessHead变量地址的五种方法也可以获取KdpDebuggerDataListHead
PsActiveProcessHead的定义: 在windows系统中,所有的活动进程都是连在一起的,构成一个双链表,表头是全局变量PsActiveProcessHead,当一个进程被创建时,其Act ...
- 介绍了如何取成员函数的地址以及调用该地址:C++
摘要:介绍了如何取成员函数的地址以及调用该地址. 关键字:C++成员函数 this指针 调用约定 一.成员函数指针的用法 在C++中,成员函数的指针是个比较特殊的东西.对普通的函数指针来说,可以视为一 ...
- 直接调用类成员函数地址(用汇编取类成员函数的地址,各VS版本还有所不同)
在C++中,成员函数的指针是个比较特殊的东西.对普通的函数指针来说,可以视为一个地址,在需要的时候可以任意转换并直接调用.但对成员函数来说,常规类型转换是通不过编译的,调用的时候也必须采用特殊的语法. ...
- C++ 获取类成员函数地址方法 浅析
C语言中可以用函数地址直接调用函数: void print () { printf ("function print"); } typdef void (*fu ...
- c++使用map保存成员函数地址
note 本基于c++11介绍一种使用map保存成员函数地址 可避免使用 if 和 switch 配置灵活 方便, 代码维护效率高 结果: 范例开始 头文件包含 #include <iostre ...
- C++(十六) — 类中引用成员函数、命名空间的使用
1.为什么类中引用成员函数? 类将属性和方法做了封装.类是一种数据类型,也就是:固定大小内存块的别名. 类的定义是一个抽象的概念,定义时不分配内存,当用类定义对象时,才分配一个固定大小的内存块. 此时 ...
- 【Java.Regex】使用正则表达式查找一个Java类中的成员函数
代码: import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; imp ...
随机推荐
- background 背景图片 在IE8中不显示解决方法
我给ul加了一个背景图片 background 火狐 ie9 ch都显示.唯独在IE8中不显示 之前的样式代码 background: url( rgba(, , , ); 在ie8中改成 backg ...
- Testbench结构篇
对于standalone的block的verification: 采用结构化的Testbench:Testcase与Harness,BFM分别分离,来提高系统的可重用性.如图是一个典型结构: 其中所有 ...
- 浅谈CDN加速问题
(以百度CDN进行分析) 婆说婆有理,公说公有理.是否使用CDN,不同的工程师有不同的意见. 这里呢我来进行一下简单的分析. [正方观点] 1. 提升网站加载速度:CDN通过缓存技术提升网站打开速度, ...
- 原生 ajax
1.创建XMLHttpRequest对象 var xmlhttp; if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Ope ...
- pandas练习(三)------ 数据分组
探索酒类消费数据 相关数据见(github) 步骤1 - 导入pandas库 import pandas as pd 步骤2 - 数据集 path3 = "./data/drinks.csv ...
- linux常见命令ps的应用
ps(Process Status)命令是linux中最常见的命令之一,它用来列出当前系统运行中的进程的状态信息.当然了,它只显示命令执行时的进程状态,如果想要动态列出状态信息,可以选择使用top命令 ...
- 自动对比度的opencv实现
在http://www.cnblogs.com/Imageshop/archive/2011/11/13/2247614.html 一文中,作者给出了“自动对比度”的实现方法,非常nice 实际实现过 ...
- 《课程设计》——cupp的使用
<课程设计>--cupp的使用 cupp简介 cupp是强大的字典生成脚本.它是一款用Python语言写成的可交互性的字典生成脚本.尤其适合社会工程学,当你收集到目标的具体信息后,你就可以 ...
- FSMC(STM32)
(一)FSMC:Flexible Static Memory Controller,可变(灵活)静态存储控制器 小容量产品是指闪存存储器容量在1 6K至32K 字节之间的STM32F101xx.STM ...
- Python3基础 os.path.splitext 处理文件名,得到文件名+扩展名
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...