回調函數是用指針來調用的函數,最常使用的回調函數就是在創建線程時,以一個函數指針以及傳遞給這個函數多個參數來調用線程函數來創建線程。那麼一般的類成員函數是不能用作回調函數的,因爲庫函數在使用回調函數時,都會傳遞指定的符合回調函數聲明的的參數給回調函數,而類成員函數隱式包含一個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創建線程時的回調函數,它是全局的,不屬於類內。因爲該回調函數需要打印類內成員,所以需要傳遞類對象給它。執行結果如圖:靜態函數作爲回調函數代碼如下:
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。執行結果如圖: