c++ 類成員函數 作回調函數

今天寫了一個類,類中用到了創建線程函數:_beginthreadex()  (windows下的創建線程函數,這其實是一個C標準的線程函數,但跟windows聯繫緊密,只要是爲解決Create_Thread()函數創建的線程如果調用了C函數庫,就會發生內存泄露,所以這是個安全的函數,建議用這個。)  以下是一個成員函數的某段代碼:

HANDLE   hth;
unsigned  uiThread1ID;
	hth = (HANDLE)_beginthreadex( NULL,         // security
                                   0,            // stack size
                                   NetRawThreadProc,
                                   this,           // arg list
                                   0,  // so we can later call ResumeThread()
                                   &uiThread1ID );
	CloseHandle(hth);

功能就是創建一個線程,然後線程去執行NetRawThreadProc(),這個NetRawThreadProc 也是一個類成員函數,它的原型爲:


void*  NetWorkThread::NetRawThreadProc (void* pParam)
{
//blablabla~~~
}

然後編譯一下,傻眼了,說該成員函數與回調類型不匹配噢,MLGB!

我從頭到尾都是參照標準的方法,來調用回調函數啊(因爲還不知道this指針這個鬼~)

所以我的解決思路是:

1. 回調類型不匹配,我就先check 我的NetRawThreadProc() 的返回值類型、參數類型,發現沒有錯;

2.是否_beginthreadex()的第三個參數給錯了,然後查到這第三個參數,有兩種使用方式,一種是在調用的函數名前面加 & ,一種是不加:

函數名,本來就是函數地址,這時候再加個 & 也是一樣,地址不會發生改變,所以還是能夠調用;

3.可能是NetWorkThread::有問題:

try了一下,把NetWrokThread:: 去掉後再來調用,就一切正常。

找到問題了,成員函數作爲回調函數,會出問題。

解決方法一:

用普通函數來做中間層:

void* func(void*)

普通函數爲上述格式,然後利用回調函數的特性,傳遞 this 指針到第四個參數,然後func()就可以使用this指針來調用類成員函數了,相當折中。

但我不喜歡這個方式,因爲這樣封裝性就破壞了。


這個時候有第二種解決方法:使用static 成員函數作爲回調函數,然後在static中調用成員函數;


void* NetWorkThread::NetRawThreadProc (void* pParam)
{
	NetThreadProc();
}


此時編譯報錯,提示NetThreadProc也需要是靜態成員;我在這裏調用成員函數,而不是直接用static成員函數來進行操作,是因爲static要操作的類成員變量必須是static的,這樣我就需要把成員變量該爲static了。所以必須要用某種方法來調用成員函數。

我們可以利用回調函數傳遞this指針,迂迴解決這個問題:

void* NetWorkThread::NetRawThreadProc (void* pParam)
{
	NetWorkThread *netObject = (NetWorkThread*)pParam;
	netObject->NetThreadProc();
}

這樣,類成員函數就能正確調用了,整體格式爲:


HANDLE   hth;
unsigned  uiThread1ID;
	hth = (HANDLE)_beginthreadex( NULL,         // security
                                   0,            // stack size
                                   NetRawThreadProc,
                                   this,           // arg list
                                   0,  // so we can later call ResumeThread()
                                   &uiThread1ID );
	CloseHandle(hth);

void* NetWorkThread::NetRawThreadProc (void* pParam)
{
	NetWorkThread *netObject = (NetWorkThread*)pParam;
	netObject->NetThreadProc();
}

void NetWorkThread::NetThreadProc(){//blablalbla}


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