什麼是回調函數?程序員
簡而言之,回調函數就是一個經過函數指針調用的函數。若是你把函數的指針(地址)做爲參數傳遞給另外一個函數,當這個指針被用爲調用它所指向的函數時,咱們就說這是回調函數。算法
爲何要使用回調函數?shell
由於能夠把調用者與被調用者分開。調用者不關心誰是被調用者,全部它需知道的,只是存在一個具備某種特定原型、某些限制條件(如返回值爲 int )的被調用函數。函數
若是想知道回調函數在實際中有什麼做用,先假設有這樣一種狀況,咱們要編寫一個庫,它提供了某些排序算法的實現,如冒泡排序、快速排序、 shell 排序、 shake 排序等等,但爲使庫更加通用,不想在函數中嵌入排序邏輯,而讓使用者來實現相應的邏輯;或者,想讓庫可用於多種數據類型( int 、 float 、 string ),此時,該怎麼辦呢?可使用函數指針,並進行回調。指針
回調可用於通知機制,例如,有時要在程序中設置一個計時器,每到必定時間,程序會獲得相應的通知,但通知機制的實現者對咱們的程序一無所知。而此時,就需有一個特定原型的函數指針,用這個指針來進行回調,來通知咱們的程序事件已經發生。實際上, SetTimer() API 使用了一個回調函數來通知計時器,並且,萬一沒有提供回調函數,它還會把一個消息發往程序的消息隊列。排序
另外一個使用回調機制的 API 函數是 EnumWindow() ,它枚舉屏幕上全部的頂層窗口,爲每一個窗口調用一個程序提供的函數,並傳遞窗口的處理程序。若是被調用者返回一個值,就繼續進行迭代,不然,退出。 EnumWindow() 並不關心被調用者在何處,也不關心被調用者用它傳遞的處理程序作了什麼,它只關心返回值,由於基於返回值,它將繼續執行或退出。接口
無論怎麼說,回調函數是繼續自 C 語言的,於是,在 C++ 中,應只在與 C 代碼創建接口,或與已有的回調接口打交道時,才使用回調函數。除了上述狀況,在 C++ 中應使用虛擬方法或函數符( functor ),而不是回調函數。隊列
什麼是鉤子函數?事件
鉤子其實是一個處理消息的程序段,經過系統調用,把它掛入系統。每當特定的消息發出,在沒有到達目的窗口前,鉤子程序就先捕獲該消息,亦即鉤子函數先獲得控制權。這時鉤子函數便可以加工處理(改變)該消息,也能夠不做處理而繼續傳遞該消息,還能夠強制結束消息的傳遞。對每種類型的鉤子由系統來維護一個鉤子鏈,最近安裝的鉤子放在鏈的開始,而最早安裝的鉤子放在最後,也就是後加入的先得到控制權。原型
也能夠這樣,更容易理解:回調函數就好像是一箇中斷處理函數,系統在符合你設定的條件時自動調用。爲此,你須要作三件事:
1. 聲明;
2. 定義;
3. 設置觸發條件,就是在你的函數中把你的回調函數名稱轉化爲地址做爲一個參數,以便於系統調用。
聲明和定義時應注意:回調函數由系統調用,因此能夠認爲它屬於WINDOWS系統,不要把它看成你的某個類的成員函數
回調函數是一個程序員不能顯式調用的函數;經過將回調函數的地址傳給調用者從而實現調用。回調函數使用是必要的,在咱們想經過一個統一接口實現不一樣的內容,這時用回掉函數很是合適。好比,咱們爲幾個不一樣的設備分別寫了不一樣的顯示函數:void TVshow(); void ComputerShow(); void NoteBookShow()...等等。這是咱們想用一個統一的顯示函數,咱們這時就能夠用回掉函數了。void show(void (*ptr)()); 使用時根據所傳入的參數不一樣而調用不一樣的回調函數。