CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
IBM Rational 系统开发最佳实践工具包 WebSphere MQ 最佳实践 TOP 15
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  C++ 语言

C++成员函数怎么转换成C函数指针?

楼主1GGHZ()2006-03-13 22:03:06 在 C/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

相关问题

  • 函数指针的类型转换:普通C函数 和 类成员函数 怎么相互转换?
  • C++ 函数指针问题?
  • 成员函数指针-----C++小问题
  • C++中函数指针的作用
  • 函数指针
  • 指针函数
  • 函数指针
  • 函数指针
  • 函数指针
  • 请问C#的数制转换函数?

关键词

  • c++
  • 函数
  • 指针
  • 模版
  • cfunc
  • pfunc
  • dothing
  • onmsg
  • 成员
  • cmyclass

得分解答快速导航

  • 帖主:1GGHZ
  • ox_thedarkness
  • iGray

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo