[C++] 回調函數(轉)
什麽是回調(Callback)函數
回調函數(Callback Function)是怎樣一種函數呢?
函數是用來被調用的,我們調用函數的方法有兩種:
直接調用:在函數A的函數體裏通過書寫函數B的函數名來調用之,使內存中對應函數B的代碼得以執行。這裏,A稱為“主叫函數”(Caller),B稱為“被叫函數”(Callee)。
間接調用:在函數A的函數體裏並不出現函數B的函數名,而是使用指向函數B的函數指針p來使內存中屬於函數B的代碼片斷得以執行——聽起來很酷,是吧。
比起直接調用來,間接調用的確麻煩,那為什麽還要使用間接調用呢?原因很簡單——直接調用把函數名都寫進函數體了,經過編譯器那麽一編譯,板上釘釘,A
如果你能明白上面一段話,OK,那麽你已經明白回調函數的75%了——因為被間接調用的函數就是回調函數本身,而間接調用是使用回調函數的“第二步”。
“第一步”又是什麽呢?讓我們仔細想想,A通過p來調用B(或者調用其它函數),p是一個指針——空指針是不能用的!所以,“第一步”就是聲明函數指針變量p
這樣,使用回調函數的完整流程就成了這樣:
聲明函數指針p -> 向函數指針p賦值,使之指向函數B -> 把p作為參數傳給函數A -> 函數A通過指針p調用函數B -> 函數B的函數體得以執行。
現在一個令人迷惑的問題擺在眼前了——Callback這個詞裏有一個back,上面這個過程哪裏體現出“回”了呢?實際上是這樣的:
函數指針p的來路我們不必去追究——它可能是一個全局變量(大部分情況下是這樣),也可能是一個臨時變量——對p賦值卻是一件著實重要的事情,除了在聲明它的時候對它初始化,我們只能在某個函數中去執行對p
現在想想,臺灣的IT同仁保留了Callback一詞的英語詞條直譯,就叫“回呼函數”,真是高明。將Callback特化成計算機專業術語、叫做“回調”真不知道是誰的主意:p
小牛試刀
咱們老規矩,貼段代碼放在這兒供大家拍磚玩兒。
//---------------------------------------------- // 水之真諦 // http://blog.csdn.net/FantasiaX //---------------------------------------------- #include <iostream> // 聲明一個函數指針,返回值為void,接受一個整形參數 typedef void (*FunctionPointer)( ); void Function_A( ); void Function_B( FunctionPointer ); void Function_C( ); void Function_D( ); // 回調過程的原始發起者 void Function_A( ) { FunctionPointer p = 0; std::cout << "Please give me a choice, 1 or 2." << std::endl; int choice = 0; std::cin >> choice; if(choice == 1) p = &Function_C; else if(choice ==2 ) p = &Function_D; else return; Function_B( p ); } // 回調過程中的“主叫函數”,Caller void Function_B(FunctionPointer p) { p( ); } // 回調過程中的“被叫函數”,Callee // 也就是回調函數本身,回調函數-1 void Function_C( ) { std::cout << "I am Function_C. Merry Christmas!" << std::endl; } //回調函數-2 void Function_D( ) { std::cout << "I am Function_D. Happy New Year!" << std::endl; } int main(int argc, char *argv[]) { Function_A( ); return 0; }
法律聲明:本文章受到知識產權法保護,任何單位或個人若需要轉載此文,必需保證文章的完整性(未經作者許可的任何刪節或改動將視為侵權行為)。若您需要轉載,請務必註明文章出處為CSDN以保障網站的權益;請務必註明文章作者為劉鐵猛(http://blog.csdn.net/FantasiaX ),並向[email protected]發送郵件,標明文章位置及用途。轉載時請將此法律聲明一並轉載,謝謝!
[C++] 回調函數(轉)