在層次化程序設計中,上層模塊可以直接調用下層模塊的函數,而下層模塊一般不能直接調用上層模塊的函數。而實際情況中卻常常存在層間相互依賴的情況,即層間相互調用函數,例如,層B的狀態變化需要通知層A或者引起層B的狀態變化,爲了避免這種相互依賴,可以使用回調函數。假設層A位於層B的上層,層A調用層B的函數,稱層A爲caller,層B中被調用的函數被稱爲callee,層A中被callee回調的函數稱爲callbacker。
1. 回調函數
回調函數是通過caller向callee傳遞callbacker的函數指針實現,當在callee中callbacker被調用時,稱爲發生回調,而callbacker則稱爲回調函數。callee無需關心callbacker的實現細節和所處理的具體的數據類型,僅需知道callbacker的原型即可,而callbacker的實現由caller負責,其中包括實現細節(算法)和數據類型。
回調函數可以實現動態綁定,即通過在運行時向callee傳遞不同的函數指針,從而調用不同的函數。例如,排序算法中需要按某種規則比較數據,callee無需知道數據比較的方法以及數據的類型,而僅僅關心比較數據的個數以及比較結果的含義,具體的比較操作由callbacker負責,數據類型可以是原始數據類型也可以是結構體類型。
回調可以實現消息通知和事件驅動,比如callee中發生某個事件時,需要通知caller或者需要caller完成某種功能,則可以通過回調機制實現。
2. 函數指針
回調機制是通過傳遞函數指針實現,而函數指針則是指向函數的指針,函數指針的定義可以使用兩種形式:
(1)直接定義
函數返回類型 (*函數指針名)(形參表);
(2)使用typedef
typedef 函數返回類型 (*新類型名)(形參表);
新類型名 函數指針名;
int add_int(int a, int b){return a+b;}
int (*pfunc)(int x, int y);
pfun = add_int;//或者&add_int
typedef int (*PFUNC)(int x, int y);
PFUNC pfunx;
pfunx = &add_int;
3. 返回函數指針的函數
即函數的返回值是一個函數指針,也可以有兩種定義形式:
(1)直接定義
函數返回類型 (*函數名(形參表1))(形參表2){......}
定義了一個名稱由“函數名”標識的函數,其參數由“形參表1”標識,該函數返回一個函數指針,指向一個由“函數返回類型”標識返回類型、參數個數以及類型符合“形參表2”的函數。
(2)使用typedef
typedef 函數返回類型 (*新類型名)(形參表2);
新類型名 函數名(形參表1){......}
實例: void (*signal(int sig, void (*func)(int)))(int); 函數名:signal 功能:指定處理信號的函數,sig指定信號,func爲處理該信號的函數,具有一個整型的參數 返回值:爲一個函數指針,指向一個具有一個整型參數、返回值類型爲void的函數,該函數參數類型以及返回值類型與func函數一致;即返回該信號之前的處理函數
|
4. 函數指針數組
指向一組有相同返回類型以及參數個數和順序的函數,常用來替換switch/if結構,也可以有兩種定義形式:
(1)直接定義
函數返回類型 (*函數指針數組名[N])(形參表);
(2)使用typedef
typedef 函數返回類型 (*新類型名)(形參表);
新類型名 函數指針數組名[N];