C++成员函数怎么转换成C函数指针?
有一个C函数
typedef void(*CFUNC)(int,int);
DoSomeThing( CFUNC pFunc );
接受一个C函数指针做为参数,
class CMyClass
{
public:
void DoThing( int ,int );
}
我现在要把这个类的成员函数DoThing传给他,应该怎么做。
谢谢各位了。
问题点数:100、回复次数:17Top
1 楼MagicCarmack(MagiC++)回复于 2006-03-13 22:08:23 得分 0
声明一个指向类函数的指针,然后把这个当作参数传入你的函数Top
2 楼sinkileu(小心)回复于 2006-03-13 22:11:41 得分 0
extern "C" 并统一调用约定__stdcall或__cdecl试试看.Top
3 楼du51(郁郁思扬)回复于 2006-03-13 22:24:08 得分 0
我现在要把这个类的成员函数DoThing传给他,应该怎么做。
函数名进去就行了.
Top
4 楼du51(郁郁思扬)回复于 2006-03-13 22:50:15 得分 0
晕..不好意思.刚才我试了一下,不行...Top
5 楼qybao(阿宝)回复于 2006-03-13 22:51:41 得分 0
have a try
CMyClass mycls;
CFUNC pFunc = mycls.DoThing;
DoSomeThing(pFunc);Top
6 楼wshcdr(dd)回复于 2006-03-13 22:56:41 得分 0
typedef void(*CFUNC)(int,int);
DoSomeThing( CFUNC pFunc );
///////////
typedef void(*CMyClass::CFUNC)(int,int);
DoSomeThing( CFUNC pFunc );
Top
7 楼iwantfat(rock)回复于 2006-03-13 23:07:00 得分 0
关注!Top
8 楼ox_thedarkness()回复于 2006-03-14 00:01:54 得分 50
- - 怎么说呢,不好做。 要调用 CMyClass::DoThing 必须指定对象的this。
我的解决方案是用全局变量保存this。问题是,全局变量只有一套数据,下次使用就会覆盖上一次的设置。
下面的代码显示了如何完成这一技术。 简单的封装了一下,更通用的做法可以用模版 —— 但是我还是想不出如何不使用全局变量。
typedef void( *CFUNC )( int,int );
void DoSomeThing( CFUNC pFunc ){
pFunc( 10, 20 );
}
class CMyClass{
public:
void DoThing( int i,int j ){ cout<< i <<' '<< j<<endl; }
};
// CallBack of CMyClass 的封装。
class cb_CMyClass{
typedef void ( CMyClass::* C_MFUNC )( int, int );
static CMyClass* pthis;
static C_MFUNC pfunc;
// 回调函数。 用当前注册的 pthis 调用 当前注册的 pfunc
static void cb_func( int i, int j ){
if( pthis && pfunc ) ( pthis->*pfunc )( i, j );
}
public:
// get_CallBack, 设置属性并返回回调函数。
// 缺点是,属性保存为全局变量,一次只能设置一个回调函数
static CFUNC getCB( CMyClass* pt, C_MFUNC pf ){
pthis = pt;
pfunc = pf;
return cb_func;
}
};
CMyClass* cb_CMyClass::pthis;
cb_CMyClass::C_MFUNC cb_CMyClass::pfunc;
int main(){
CMyClass c;
// cb_CMyClass::getCB 返回一个回调函数指针。
// 他的参数是:设置当前 CMyClass 对象,以及需要回调的函数
// 但是:注意! 他们都是static成员。 所以这两个数据只有一套!
// 下次使用就会覆盖上次 this 和 func 设置!
//
DoSomeThing( cb_CMyClass::getCB( &c, &CMyClass::DoThing ) );
}
Top
9 楼xiaocai0001(高楼目尽欲黄昏/梧桐叶上萧萧雨)回复于 2006-03-14 08:20:02 得分 0
非静态成员函数与全局函数的最大区别就是在于有this指针, 怎么样把this指针传入就是一个很大的问题.Top
10 楼ugg(逸学堂(exuetang.net))回复于 2006-03-14 08:59:51 得分 0
我现在要把这个类的成员函数DoThing传给他,应该怎么做。
~~~~~~~~~~~
必须把类的成员函数声明为staticTop
11 楼iGray(i_冲锋陷阵)回复于 2006-03-14 10:27:34 得分 50
To:楼主
指向成员函数的指针并非指针,是一个类内偏移加1
non-static函数,不能用作回调函数,因为函数的第一个参数是隐含的this指针,所以与回调类型不匹配了。
To:ox_thedarkness(),这样你也想得出来:)加一个包装器上去,强啊。
OK把你的方法再加一个m_pthis指针上去,用于保存所指对象,这样就可以避免你所说的单一的static了。不过,要使用具体哪个对象的回调函数前,必须reset()一下static的那个指针值:),当然也可以把reset()放在构造函数里。
修改过的代码如下:
// DosTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
typedef void( *CFUNC )( int,int );
void DoSomeThing( CFUNC pFunc ){
pFunc( 10, 20 );
}
class CMyClass{
public:
void DoThing( int i,int j ){ cout<< i <<' '<< j<<endl; }
};
// CallBack of CMyClass 的封装。
class cb_CMyClass{
typedef void ( CMyClass::* C_MFUNC )( int, int );
static CMyClass* pthis;
static C_MFUNC pfunc;
// 回调函数。 用当前注册的 pthis 调用 当前注册的 pfunc
static void cb_func( int i, int j ) {
if ( pthis && pfunc ) ( pthis->*pfunc )( i, j );
}
public:
// get_CallBack, 设置属性并返回回调函数。
// 缺点是,属性保存为全局变量,一次只能设置一个回调函数
static CFUNC getCB( C_MFUNC pf ) {
pfunc = pf;
return cb_func;
}
//----------------------------------------------
public:
explicit cb_CMyClass(CMyClass& pt):m_pthis(&pt) {}
void reset() { pthis = m_pthis; }
private:
CMyClass* m_pthis;
};
CMyClass* cb_CMyClass::pthis;
cb_CMyClass::C_MFUNC cb_CMyClass::pfunc;
int main(){
CMyClass c;
// cb_CMyClass::getCB 返回一个回调函数指针。
// 他的参数是:设置当前 CMyClass 对象,以及需要回调的函数
// 但是:注意! 他们都是static成员。 所以这两个数据只有一套!
// 下次使用就会覆盖上次 this 和 func 设置!
/* modified by igray
* 添加了一个成员变量来保存对象状态和reset()函数来重置static的pthis
*/
cb_CMyClass cb_wrapper(c);
cb_wrapper.reset();
DoSomeThing( cb_CMyClass::getCB( &CMyClass::DoThing ) );
}
Top
12 楼1GGHZ()回复于 2006-03-14 13:55:53 得分 0
好像有看到用Boost::bind可以,但不知道怎么使用,又知道吗的。Top
13 楼ox_thedarkness()回复于 2006-03-14 14:22:44 得分 0
- - iGray(i_冲锋陷阵) ( ) 没解决根本问题,即:无论如何,一次都只有一个回调函数。
考虑一个实时,或者基于消息的系统,其中很多地方需要注册回调函数,要求多个回调函数能长期同时可用。 这就很难解决了。
我仅能提供的思路是,提供一个这样的模版:
template< int cb_id >
//....
用户维护一个静态 id 列表,在每个需要不同回调函数的时候使用不同的模版实例。
于是用起来类似这样:
set_OnMsg( func< CB_ON_MSG >( &a, A::onMsg ) );
set_OnError( func< CB_ON_ERR >( &a, A::onErr ) );
要是能直接这样用多好:
set_OnMsg( func( &a, A::onMsg ) );
set_OnError( func( &a, A::onErr ) );
也就是说,要是有办法能令每次调用 func 都产生不同的模版实例就好了~~~
////////////////////////////////////////////////////////
另外,若是要封装通用模版有更大的问题。 如何定义一个模版,令他能动态识别函数类型,并且产生回调函数呢?
比如, 下面的定义
template < class T, class F, class FRet >
T* pthis
F* f
返回 FRet*
这样可以接受任何类型、以及我们需要的任何类型函数指针
但是,当我们调用 (pthis->* f)( ) 的时候,参数表怎么写呢....Top
14 楼firetoucher(风焱)回复于 2006-03-14 14:23:19 得分 0
不行,除非
1 将成员函数申明为static成员函数
2 “模拟执行”成员函数,在C中加入接受this指针的附加参数,然后强制转化。不过这个可能不通用。
3 用BCB,里面有一个非C++标准的扩展closure关键字可以达到这个目的。
FT
--
Anything one man can imagine, other men can make real.Top
15 楼iGray(i_冲锋陷阵)回复于 2006-03-14 17:54:42 得分 0
To ox_thedarkness()
考虑一个实时,或者基于消息的系统,其中很多地方需要注册回调函数,要求多个回调函数能长期同时可用。
//-----------------------------------------------------
如果真像上面说的,回调函数要具有自身状态,用“函数对象”不就完了。
不需要回调时具有状态,就直接用static就完了。
用模板跟据不同id来实例化,哇。。。你也是强,尽想些不同寻常的方法,佩服:)Top
16 楼ox_thedarkness()回复于 2006-03-14 23:59:35 得分 0
To iGray(i_冲锋陷阵) ( )
回调函数要具有自身状态,用“函数对象”不就完了。
//------------------------------------------
问题是,目标只接受真正的函数指针,即一个4字节调转地址(32位编译器上)。 函数对象要么塞不进去, 要么提供一个 callback 函数指针仍然避免不了 static 变量保存状态 —— 转了一圈还是回到原点。Top
17 楼lilachue(静水思雅)回复于 2006-07-03 16:35:03 得分 0
学习!Top




