我在自己上一篇博文《C++類成員函數指針使用實例》中已經寫了怎麼跨類地使用類成員函數指針的,但,但沒有處理成員函數指針裏隱含的this指針,所以在被調用的成員函數裏使用this指針時,就會讓人抓狂,因爲this根本無法用。經過一晚上的研究,當然無法避免參考別人的代碼,於是將成員函數指針的使用打包成了一個類——事實上也只是保存好this指針與成員函數指針而已,其代碼如下:
- #ifndef _Q_CALLBACK_FUNCTION_H_
- #define _Q_CALLBACK_FUNCTION_H_
- //獲取類成員函數的地址值
- template<typename TFuncAddr,typename PtrFunc>
- void GetMemberFuncAddr(TFuncAddr& addr, PtrFunc func)
- {
- union
- {
- PtrFunc _func;
- TFuncAddr _addr;
- }ut;
- ut._func = func;
- addr = ut._addr;
- }
- //void (*function)(void) 類型的函數指針
- typedef void (__stdcall * FUNCTION_CALLBACK)(void * This);
- //////////////////////////////////////////////////////////////////////////
- //回調函數類
- class CMemberFunction
- {
- private:
- //類的this指針
- void * _dwPtrThis;
- //成員函數
- FUNCTION_CALLBACK _tagFunc;
- public:
- //添加一個成員函數
- template<typename PtrThis, typename PtrFunc>
- void AddMemberFunction(PtrThis ptrThis, PtrFunc ptrFunc)
- {
- this->_dwPtrThis = (void *)ptrThis;
- DWORD dwAddr = 0;
- GetMemberFuncAddr(dwAddr, ptrFunc);
- this->_tagFunc = (FUNCTION_CALLBACK)dwAddr;
- }
- //調用函數
- void CallMemberFunction(void)
- {
- this->_tagFunc(this->_dwPtrThis);
- }
- };
- #endif //_Q_CALLBACK_FUNCTION_H_
而此類的使用,如下代碼:
- class A_Class
- {
- private:
- //回調函數管理類
- CMemberFunction _MemberFuction;
- //其他內容
- //...
- public:
- //模板函數,添加一個回調函數
- //PtrThis 目標類的this指針
- //PtrFunc 目標類的成員函數
- template<typename PtrThis, typename PtrFunc>
- void AddMemberFuction(PtrThis ptrThis, PtrFunc ptrFunc)
- {
- this->_MemberFuction.AddMemberFunction(ptrThis, ptrFunc);
- }
- //調用回調函數
- void CallMemberFunction(void)
- {
- this->_MemberFuction.CallMemberFunction();
- }
- //其他類的內容
- //...
- };
- class B_Class
- {
- private:
- //成員變量
- int num;
- //A_Class類的變量
- A_Class aClass;
- public:
- //被調用的函數
- void __stdcall TestFunction(void)
- {
- this->num++;
- TRACE(_T("%d\r\n"),this->num);
- }
- //本類的初始化
- void Init(void)
- {
- this->num = 0;
- aClass = A_Class();
- aClass.AddMemberFuction(this, &B_Class::TestFunction);
- }
- //調用,也可以在A_Class內部調用
- void Callback(void)
- {
- aClass.CallMemberFunction();
- }
- };
雖然很多人喜歡將示例代碼放到main中,但以上是我實際的使用情況,如此一來,被回調的成員函數TestFunction中的this指針就準確無疑了,就不會出現不知指向的情況了,別看代碼不多,但真是搞死人的,我承認,俺是低手。
還需要提醒的是,在此我只處理一種調用類型的函數,即
- //void (*function)(void) 類型的函數指針
- typedef void (__stdcall * FUNCTION_CALLBACK)(void * This);
__stdcall還有__thiscall是VC中兩中不同的函數調用方式,其具體內涵我還沒時間深入瞭解,以後再說吧。然後,我這裏的成員函數是不帶參數的,如果需要帶參數就請參考我的上一篇文章裏提供的連接吧,以上我用的是VS2008。
最後吐槽一下,搞這個問題搞到凌晨3點,碼農真TMD傷不起啊!!!!