我在自己上一篇博文《C++类成员函数指针使用实例》中已经写了怎么跨类地使用类成员函数指针的,但,但没有处理成员函数指针里隐含的this指针,所以在被调用的成员函数里使用this指针时,就会让人抓狂,因为this根本无法用。经过一晚上的研究,当然无法避免参考别人的代码,于是将成员函数指针的使用打包成了一个类——事实上也只是保存好this指针与成员函数指针而已,其代码如下:

  1. #ifndef _Q_CALLBACK_FUNCTION_H_ 
  2. #define _Q_CALLBACK_FUNCTION_H_ 
  3.  
  4. //获取类成员函数的地址值 
  5. template<typename TFuncAddr,typename PtrFunc> 
  6. void GetMemberFuncAddr(TFuncAddr& addr, PtrFunc func) 
  7.     union 
  8.     { 
  9.         PtrFunc _func; 
  10.         TFuncAddr _addr; 
  11.     }ut; 
  12.     ut._func = func; 
  13.     addr = ut._addr; 
  14.  
  15. //void (*function)(void) 类型的函数指针 
  16. typedef void (__stdcall * FUNCTION_CALLBACK)(void * This); 
  17.  
  18. ////////////////////////////////////////////////////////////////////////// 
  19. //回调函数类 
  20. class CMemberFunction 
  21. private
  22.  
  23.     //类的this指针 
  24.     void * _dwPtrThis; 
  25.      
  26.     //成员函数 
  27.     FUNCTION_CALLBACK _tagFunc; 
  28.  
  29. public
  30.  
  31.     //添加一个成员函数 
  32.     template<typename PtrThis, typename PtrFunc> 
  33.     void AddMemberFunction(PtrThis ptrThis, PtrFunc ptrFunc) 
  34.     { 
  35.         this->_dwPtrThis = (void *)ptrThis; 
  36.         DWORD dwAddr = 0; 
  37.         GetMemberFuncAddr(dwAddr, ptrFunc); 
  38.         this->_tagFunc = (FUNCTION_CALLBACK)dwAddr; 
  39.     } 
  40.  
  41.     //调用函数 
  42.     void CallMemberFunction(void
  43.     { 
  44.         this->_tagFunc(this->_dwPtrThis); 
  45.     } 
  46. }; 
  47.  
  48. #endif //_Q_CALLBACK_FUNCTION_H_ 

而此类的使用,如下代码:

  1. class A_Class 
  2. private
  3.  
  4.     //回调函数管理类 
  5.     CMemberFunction _MemberFuction; 
  6.  
  7.     //其他内容 
  8.     //... 
  9.  
  10. public
  11.  
  12.     //模板函数,添加一个回调函数 
  13.     //PtrThis 目标类的this指针 
  14.     //PtrFunc 目标类的成员函数 
  15.     template<typename PtrThis, typename PtrFunc> 
  16.     void AddMemberFuction(PtrThis ptrThis, PtrFunc ptrFunc) 
  17.     { 
  18.         this->_MemberFuction.AddMemberFunction(ptrThis, ptrFunc); 
  19.     } 
  20.  
  21.     //调用回调函数 
  22.     void CallMemberFunction(void
  23.     { 
  24.         this->_MemberFuction.CallMemberFunction(); 
  25.     } 
  26.  
  27.     //其他类的内容 
  28.     //... 
  29. }; 
  30.  
  31. class B_Class 
  32. private
  33.  
  34.     //成员变量 
  35.     int num; 
  36.  
  37.     //A_Class类的变量 
  38.     A_Class aClass; 
  39.  
  40. public
  41.  
  42.     //被调用的函数 
  43.     void __stdcall TestFunction(void
  44.     { 
  45.         this->num++; 
  46.         TRACE(_T("%d\r\n"),this->num); 
  47.     } 
  48.  
  49.     //本类的初始化 
  50.     void Init(void
  51.     { 
  52.         this->num = 0; 
  53.         aClass = A_Class(); 
  54.         aClass.AddMemberFuction(this, &B_Class::TestFunction); 
  55.     } 
  56.  
  57.     //调用,也可以在A_Class内部调用 
  58.     void Callback(void
  59.     { 
  60.         aClass.CallMemberFunction(); 
  61.     } 
  62. }; 

虽然很多人喜欢将示例代码放到main中,但以上是我实际的使用情况,如此一来,被回调的成员函数TestFunction中的this指针就准确无疑了,就不会出现不知指向的情况了,别看代码不多,但真是搞死人的,我承认,俺是低手。

还需要提醒的是,在此我只处理一种调用类型的函数,即

  1. //void (*function)(void) 类型的函数指针  
  2. typedef void (__stdcall * FUNCTION_CALLBACK)(void * This);  

__stdcall还有__thiscall是VC中两中不同的函数调用方式,其具体内涵我还没时间深入了解,以后再说吧。然后,我这里的成员函数是不带参数的,如果需要带参数就请参考我的上一篇文章里提供的连接吧,以上我用的是VS2008。

最后吐槽一下,搞这个问题搞到凌晨3点,码农真TMD伤不起啊!!!!