回調函數的應用誤區3(大徹大悟的回調小程序,例子的解釋相當給力)


研究了一段時間回調函數,越看越迷惑,分析並改進了從網上看到的幾篇好文,看過后有了自己的看法。我也不知道這些跌跌撞撞的認識是否符合回調的真實原理,若有大俠能幫解惑,自當感激不盡。

下面的代碼可以在Vs2008下編譯並運行:

所有的回調函數文章里,能讓我一下看明白回調函數的就是這篇文章了,描述簡單,一語中的:http://hi.baidu.com/zht7216/item/1dd32e82a68c40d15f0ec154

摘選如下:

  函數指針是一個指向函數的指針變量,它是專門來存放函數入口地址的,在程序中給它賦予哪個函數的入口地址,它就指向哪個函數,因此在一個程序中,一個函數的指針可被多次賦值,指向不同的函數。

#include <stdio.h>

int max(int x , int y);
int min(int x , int y);
int add(int x , int y);
int process(int x , int y , int(*fun)(int , int));

//客戶程序C
void main()
{
    int a=10,b=2;
    printf("a=%d, b=%d\n", a, b);
    printf("process(a,b,max)=%d\n", process(a,b,max));//注冊回調函數
    printf("process(a,b,min)=%d\n", process(a,b,min));
    printf("process(a,b,add)=%d\n", process(a,b,add));
}

int max(int x , int y)
{
    return x>y?x:y;
}

int min(int x , int y)
{
    return x<y?x:y;
}



int add(int x, int y)
{
    return x + y;
}

//服務程序S

int process(int x, int y, int(* fun)(int, int))
{
    int result;
    result = (*fun)(x , y);
    return result;
}

在這里我見到了對回調函數大徹大悟的解釋:

按照剛才的邏輯,其實所聲明的三個功能函數:max ,min ,add 就是回調函數。

      請看:

     使用回調函數實際上就是在調用某個函數時將自己的一個函數(這個函數就是回調函數)的地址作為參數傳遞給那個函數。而那個函數在需要的時候,利用傳遞的地址調用回調函數,這是你可以利用這個機會,在回調函數中處理消息或完成一定的操作。

     也可以這樣理解:

      所謂回調,就是客戶程序Client(main)調用服務程序Server中的某個函數Sa(process),然后Server又在某個時候反過來調用Client中的某個函數Ca(max),對於Client來說,這個Ca便叫做回調函數。例如Win32下的窗口過程函數就是一個典型的回調函數。

     一般說來,Client不會自己調用Ca,Client提供Ca的目的就是讓Server來調用它,而且是Client不得不提供。由於Server並不知道Client提供的Ca叫什么,所以Server會約定Ca的接口規范(函數原 型),然后由Client提前通過Server的一個函數Sr(process)告訴Server,自己將要使用Ca函數,這個過程稱為回調函數的注冊,Sr稱為注冊函數。

     這個Client的Ca函數是不是很像個鈎子?一旦將它注冊到Server后,Server就會在合適的場合來調用它了。

       下面舉個通俗的例子:
      假設公司里面有一個小神童,可以回答任何人的問題。

      某天,我向小神童請教問題,當然是個難題,:),小神童一時想不出解決方法,而后面還有一幫人正在等着神童回答他們自己的問題呢,

      現在不能因為我的提問,而影響到后面排隊的人的咨詢,所以我和小神童約定,我把手機號碼留給他,等小神童知道答案了然后再把結果告訴我。

      我就離開小神童辦其它事情去了。過了XX分鍾,我的手機響了,小神童興高采烈的說問題已經搞定,應該如此這般處理。故事到此結束。

     說明:我是Client,小神童是Server,我找小神童辦事就是調用函數Sa,由於某種原因不能馬上得到結果,又不能占用大家的時間,所以我只能先注冊(Sr函數)聯系方式給小神童, 等小神童有消息了,就打電話給我。

這個例子說明了“異步+回調”的編程模式。其中,你后來打手機告訴我結果便是一個“回調”過程;我的手機號碼必須在以前告訴你,這便是注冊回調函數;我的手機號碼應該有效並且手機能夠接收到你的呼叫,這是回調函數必須符合接口規范。

      2. 什么情況下使用回調


      如果你是SDK的使用者,一旦別人制定了回調機制,那么你被迫得使用回調函數,因此這個問題只對SDK設計者有意義。
從引入的目的看,回調大致分為三種:
1) SDK有消息需要通知應用程序,比如定時器被觸發;
2) SDK的執行需要應用程序的參與,比如SDK需要你提供一種排序算法;
3) SDK的操作比較費時,但又不能讓應用程序阻塞在那里,於是采用異步方式,讓調用函數及時返回,SDK另起線程在后台執行操作,待操作完成后再將結果通知應用程序。
經上面這樣一總結,你也許會恍然大悟:原來“回調機制”無處不在啊!
是的,不光是Win32 API編程中你會用到,也不光是其它SDK編程中會用到,平時我們自己編寫程序時也可能用到回調機制,這時,我們既是回調的設計者又是回調的使用者。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM