【转】总结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 ...
随机推荐
- testng入门教程14数据驱动(不同文件)
数据与test脚本不在同一文件时,下面是数据: package data_driver_two_parts; import org.testng.annotations.DataProvider; p ...
- Java有序数组的实现
package 有序数组; public class OrdArray { private long[]array; private int nElems; //初始化 public OrdArray ...
- winfrom 下 listbox 选项添加value
public struct MyItem { public string Name; public string Tag; public override string ToString() { re ...
- ARM_Core的处理器模式与寄存器,结构杂谈
ARM处理器的工作状态:ARM处理器有两种工作状态.在程序的执行过程中,处理器可以在两种工作状态之间切换,并且不影响 相应寄存器中的内容. ARM状态,此时处理器执行32位对齐的ARM指令:BX指令, ...
- 2016-2017-2 20155309南皓芯java第五周学习总结
教材内容总结 这一周学习的进度和前几周比较的话是差不多的,都是学习两章. 异常处理 1.理解异常架构 2.牚握try...catch...finally处理异常的方法 3.会用throw,throws ...
- 持续集成之二:搭建SVN服务器(SvnAdmin)
安装环境 Red Hat Enterprise Linux Server release 7.3 (Maipo) jdk1.7.0_80 apache-tomcat-7.0.90 mysql-5.7. ...
- python 爬虫煎蛋网
import urllib.request import os from urllib import error import re import base64 def url_open(url): ...
- 使用Spring实现读写分离( MySQL实现主从复制)(转)
本文转自:http://blog.csdn.net/jack85986370/article/details/51559232 1. 背景 我们一般应用对数据库而言都是“读多写少”,也就说对数据库读 ...
- jQuery 是javascript的一个库(常用插件、处理器)
jQuery校验官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation jQuery就是javascript的一个库,把我 ...
- sql study
-- ============================================= -- Author: lifu -- Create date: 2017-06-14 -- Descr ...