如何實現類成員函式為回撥函式
如果試圖直接使用C++的成員函式作為回撥函式將發生錯誤,甚至編譯就不能通過。通過查詢資料發現,其錯誤是普通的C++成員函式都隱含了一個傳遞函式作為引數,亦即“this”指標,C++通過傳遞this指標給其成員函式從而實現程式函式可以訪問C++的資料成員。這也可以理解為什麼C++類的多個例項可以共享成員函式卻-有不同的資料成員。由於this指標的作用,使得將一個CALL-BACK型的成員函式作為回撥函式安裝時就會因為隱含的this指標使得函式引數個數不匹配,從而導致回撥函式安裝失敗。要解決這一問題的關鍵就是不讓this指標起作用,通過採用以下兩種典型技術可以解決在C++中使用回撥函式所遇到的問題。這種方法具有通用性,適合於任何C++。
1). 不使用成員函式,為了訪問類的成員變數,可以使用友元操作符(friend),在C++中將該函式說明為類的友元即可。
2). 使用靜態成員函式,靜態成員函式不使用this指標作為隱含引數,這樣就可以作為回撥函數了。靜態成員函式具有兩大特點:其一,可以在沒有類例項的情況下使用;其二,只能訪問靜態成員變數和靜態成員函式,不能訪問非靜態成員變數和非靜態成員函式。由於在C++中使用類成員函式作為回撥函式的目的就是為了訪問所有的成員變數和成員函式,如果做不到這一點將不具有實際意義。解決的辦法也很簡單,就是使用一個靜態類指標作為類成員,通過在類建立時初始化該靜態指標,如pThis=this,然後在回撥函式中通過該靜態指標就可以訪問所有成員變數和成員函數了。這種處理辦法適用於只有一個類例項的情況,因為多個類例項將共享靜態類成員和靜態成員函式,這就導致靜態指標指向最後建立的類例項。為了避免這種情況,可以使用回撥函式的一個引數來傳遞this指標,從而實現資料成員共享。這種方法稍稍麻煩,這裡就不再贅述。
舉例:
class Test
{
public:
static void callBackFun(void){}; //因為callBackFun預設有一個const Test* 的指標
};
typedef void (*FPtr)(void);
void Fun(FPtr ptr)
{
ptr();
}
void main(void)
{
Fun(Test::callBackFun);
}