1. 程式人生 > >【C++基礎之八】函式指標和回撥函式

【C++基礎之八】函式指標和回撥函式

C++很多類庫都喜歡用回撥函式,MFC中的定時器,訊息機制,hook機制等待,包括現在在研究的cocos2d-x中也有很多的回撥函式。

1.回撥函式

什麼是回撥函式呢?回撥函式其實就是一個通過函式指標呼叫的函式!假如你把A函式的指標當作引數傳給B函式,然後在B函式中通過A函式傳進來的這個指標呼叫A函式,那麼這就是回撥機制。A函式就是回撥函式,而通常情況下,A函式是系統在符合你設定條件的情況下會自動執行,比如Windows下的訊息觸發等等。那麼呼叫者和被呼叫者的關係就被拉開了,就像是中斷處理函式那樣。

2.函式指標

函式指標是一個指標,只是這個指標它不像普通的指標指向是是一個變數,此時它指向的是一個函式,也就是它儲存的是一個函式的地址,如果我們願意的話,可以改變這個它的值,讓他由指向funA轉變為指向funB,那麼這個函式指標的作用就改變了。

3.函式指標的使用

3.1函式指標宣告

typedef 返回型別(*函式指標型別名)(函參列表);

3.2示例

typedef void(*Fun)(int,int); //定義函式指標型別
void min(int a,int b);
void max(int a,int b);

void min(int a,int b)
{
	int minvalue=a<b?a:b;
	std::cout<<"min value is "<<minvalue<<"\n";
}

void max(int a,int b)
{
	int maxvalue=a>b?a:b;
	std::cout<<"Max value is "<<maxvalue<<"\n";
}

int _tmain(int argc, _TCHAR* argv[])
{
	Fun pFun=NULL; //定義函式指標變數pFun
	//pFun=min;//兩種賦值方式都支援
	pFun=&min;
	pFun(1,2);//這裡獲得最小值
	//pFun=max;
	pFun=&max;
	pFun(1,2);//這裡獲得最大值
	return 0;
}
我想這麼寫應該是很一目瞭然了。

4.回撥函式的使用

回撥函式的使用其實和上面函式指標示例是很一致的,只是上面的例項中pFun是我們自己呼叫的。現在我們在MFC中讓系統呼叫一下吧。

先看一下SetTimer函式宣告:

UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );
其中lpfnTimer是這麼解釋的:Specifies the address of the application-supplied TimerProc callback function that processes the WM_TIMER messages. If this parameter is NULL, the WM_TIMER messages are placed in the application's message queue and handled by the CWnd object.

也就是或如果為NULL的話,系統自動觸發WM_Timer訊息,然後呼叫OnTimer函式。

我們呼叫自己的自定義回撥函式。

CALLBACK VOID callback_fun(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
	TRACE("CallBack\n");//debug下執行控制檯輸出CallBack
}

void CTestCallBackDlg::OnBnClickedButton1()
{
	// TODO: 在此新增控制元件通知處理程式程式碼
	SetTimer(1,1000,(TIMERPROC)callback_fun);//每一秒回撥一次
}

另外,需要注意的是回撥函式必須是全域性函式或者靜態成員函式,因為普通的成員函式會隱含著一個傳遞函式作為引數,也就是this指標。因此如果使用普通成員函式作為回撥函式的話會導致函式引數個數不匹配,因此編譯失敗。這也是執行緒函式是多為靜態函式的原因。

我們還注意到回撥函式用CALLBACK修飾,我們可以在windef.h中發現:

#define CALLBACK    __stdcall
CALLBACK其實就是__stdcall,還記得上篇講過的函式呼叫約定嗎?