C++類成員函數指針使用實例——關於this指針的處理

我在自己上一篇博文《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傷不起啊!!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章