簡而言之,回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作爲參數傳遞給另一個函數,當這個指針被用爲調用它所指向的函數時,我們就說這是回調函數。
爲什麼要使用回調函數?
因爲可以把調用者與被調用者分開。調用者不關心誰是被調用者,所有它需知道的,只是存在一個具有某種特定原型、某些限制條件(如返回值爲 int )的被調用函數。
如果想知道回調函數在實際中有什麼作用,先假設有這樣一種情況,我們要編寫一個庫,它提供了某些排序算法的實現,如冒泡排序、快速排序、 shell 排序、 shake 排序等等,但爲使庫更加通用,不想在函數中嵌入排序邏輯,而讓使用者來實現相應的邏輯;或者,想讓庫可用於多種數據類型( int 、 float 、 string ),此時,該怎麼辦呢?可以使用函數指針,並進行回調。
回調可用於通知機制,例如,有時要在程序中設置一個計時器,每到一定時間,程序會得到相應的通知,但通知機制的實現者對我們的程序一無所知。而此時,就需有一個特定原型的函數指針,用這個指針來進行回調,來通知我們的程序事件已經發生。實際上, SetTimer()
API 使用了一個回調函數來通知計時器,而且,萬一沒有提供回調函數,它還會把一個消息發往程序的消息隊列。
另一個使用回調機制的 API 函數是 EnumWindow() ,它枚舉屏幕上所有的頂層窗口,爲每個窗口調用一個程序提供的函數,並傳遞窗口的處理程序。如果被調用者返回一個值,就繼續進行迭代,否則,退出。 EnumWindow() 並不關心被調用者在何處,也不關心被調用者用它傳遞的處理程序做了什麼,它只關心返回值,因爲基於返回值,它將繼續執行或退出。
不管怎麼說,回調函數是繼續自 C 語言的,因而,在 C++ 中,應只在與 C 代碼建立接口,或與已有的回調接口打交道時,才使用回調函數。除了上述情況,在 C++ 中應使用虛擬方法或函數符(functor ),而不是回調函數。
例子:
#include
<stdio.h>
void PrintNum(int n);
void ShowNum(int n,void (* ptr)());
void PrintMessage1();
void PrintMessage2();
void PrintMessage3();
void ShowMessage(void (* ptr)());
int main(){
ShowNum(11111,PrintNum);
ShowNum(22222,PrintNum);
ShowMessage(PrintMessage1);
ShowMessage(PrintMessage2);
ShowMessage(PrintMessage3);
}
void PrintNum(int n){
printf("Test1 is called,the number is %d\n",n);
}
void ShowNum(int n,void (* ptr)()){
(* ptr)(n);
}
void PrintMessage1(){
printf("This is the message 1!\n");
}
void PrintMessage2(){
printf("This is the message 2!\n");
}
void PrintMessage3(){
printf("This is the message 3!\n");
}
void ShowMessage(void (* ptr)()){
(* ptr)();
}