天天看點

C++類成員函數作為線程回調函數

      C++類成員函數使用時,都會隐式傳遞一個this指針給該函數,this指針指向該類的對象。函數體可以通過顯示調用該指針或直接通路類内成員。

      回調函數是用指針來調用的函數,最常使用的回調函數就是在建立線程時,以一個函數指針以及傳遞給這個函數多個參數來調用線程函數來建立線程。那麼一般的類成員函數是不能用作回調函數的,因為庫函數在使用回調函數時,都會傳遞指定的符合回調函數聲明的的參數給回調函數,而類成員函數隐式包含一個this指針參數,是以把類成員函數當作回調函數編譯時因為參數不比對會出錯。

    如果類内成員函數調用回調函數怎麼實作呢?一般有兩種方法:

    1.回調函數聲明在類外,全局的

    傳類對象指針給回調函數即可使用類内成員,因為回調函數是全局的是以影響了類的封裝性

    2.類内成員函數作為回調函數

    利用關鍵名static聲明類内成員函數,因為類靜态成員函數隻能操作類靜态成員,是以函數若想通路類成員,隻能通過調用函數傳遞類對象指針給回調函數,或者在類内聲明一個靜态指針,該指針指向類,然後在函數中調用該指針通路類成員。

全局函數作為回調函數代碼如下:

DWORD WINAPI TestFun(LPVOID lpParam);
class Thread{								
public:
	Thread(int n,int m) :Num(n),Test(m){};
	int Test;
	int Num;
	int ThreadNew();
};
DWORD WINAPI  TestFun(LPVOID lpParam)
{
	Thread * ptrData = (Thread *)lpParam;
	cout << ptrData->Num << "   " << ptrData->Test << endl;
	return 0;
}
int Thread::ThreadNew()
{
	CreateThread(NULL, 0, TestFun, this, 0, NULL);
	return 0;
}
int main(int argc, char *argv[])
{
	int	ret, iSum;
	Thread TestData(1,2);


	TestData.ThreadNew();
	cin >> ret;
	return 0;
}
           

函數TestFun為類Thread的方法ThreadNew建立線程時的回調函數,它是全局的,不屬于類内。因為該回調函數需要列印類内成員,是以需要傳遞類對象給它。執行結果如圖:

C++類成員函數作為線程回調函數

靜态函數作為回調函數代碼如下:

class Thread{
public:
	Thread(int n,int m) :Num(n),Test(m){};
	int Test;
	int Num;
	const static int tmp = 10;
	int ThreadNew();
	static DWORD WINAPI TestFun(LPVOID lpParam);
};
DWORD WINAPI  Thread::TestFun(LPVOID lpParam)
{
	Thread * ptrData = (Thread *)lpParam;
	cout << ptrData->Num << "   " << ptrData->Test << "   " << tmp << endl;
	return 0;
}
int Thread::ThreadNew()
{
	CreateThread(NULL, 0, TestFun, this, 0, NULL);
	return 0;
}


int main(int argc, char *argv[])
{
	int	ret, iSum;
	Thread TestData(1,2);


	TestData.ThreadNew();
	cin >> ret;
	return 0;
}
           

因為tmp是靜态變量,而回調函數TestFun也是靜态函數,且同屬一個類,是以函數可以直接使用變量tmp。執行結果如圖:

C++類成員函數作為線程回調函數