閱讀52 返回首頁    go 技術社區[雲棲]


C/C++回調函數

回調函數就像您隨身帶的BP機:告訴別人號碼,在它有事情時Call您
    
    回調用於層間協作,上層將本層函數安裝在下層,這個函數就是回調,而下層在一定條件下觸發回調,例如作為一個驅動,是一個底層,他在收到一個數據時,除了完成本層的處理工作外,還將進行回調,將這個數據交給上層應用層來做進一步處理,這在分層的數據通信中很普遍。
    
    其實回調和API非常接近,他們的共性都是跨層調用的函數。但區別是API是低層提供給高層的調用,一般這個函數對高層都是已知的;而回調正好相反,他是高層提供給低層的調用,對於低層他是未知的,必須由高層進行安裝,這個安裝函數其實就是一個低層提供的API,安裝後低層不知道這個回調的名字,但它通過一個函數指針來保存這個回調,在需要調用時,隻需引用這個函數指針和相關的參數指針。
    
    其實:回調就是該函數寫在高層,低層通過一個函數指針保存這個函數,在某個事件的觸發下,低層通過該函數指針調用高層那個函數。回調在C語言中是通過函數指針來實現的,通過將回調函數的地址傳給被調函數從而實現回調。因此,要實現回調,必須首先定義函數指針,請看下麵的例子:
    
    void Func(char *s);// 函數原型
    
    void (*pFunc) (char *);//函數指針
    
    可以看出,函數的定義和函數指針的定義非常類似。
    
    一般的化,為了簡化函數指針類型的變量定義,提高程序的可讀性,我們需要把函數指針類型自定義一下。
    
    typedef void(*pcb)(char *);
    
    回調函數可以象普通函數一樣被程序調用,但是隻有它被當作參數傳遞給被調函數時才能稱作回調函數。
    
    被調函數的例子:
    
    例一:
    
    void GetCallBack(pcb callback)
    
    {
    
    /*do something*/
    
    }
    
    用戶在調用上麵的函數時,需要自己實現一個pcb類型的回調函數:
    
    void fCallback(char *s)
    
    {
    
    /* do something */
    
    }
    
    然後,就可以直接把fCallback當作一個變量傳遞給GetCallBack,
    
    GetCallBack(fCallback);
    
    如果賦了不同的值給該參數,那麼調用者將調用不同地址的函數。賦值可以發生在運行時,這樣使你能實現動態綁定。
    
    例二:
    
    //Test.c
    
    #include <stdlib.h>
    
    #include <stdio.h>
    
    int Test1()
    
    {
    
    int i;
    
    for (i=0; i<30; i++)
    
    {
    
    printf(“The %d th charactor is: %c\n”, i, (char)(‘a' + i%26));
    
    }
    
    return 0;
    
    }
    
    int Test2(int num)
    
    {
    
    int i;
    
    for (i=0; i<num; i++)
    
    {
    
    printf(“The %d th charactor is: %c\n”, i, (char)('a' + i%26));
    
    }
    
    return 0;
    
    }
    
    void Caller1(void (*ptr)())      //指向函數的指針作函數參數
    
    {
    
    (*ptr)();
    
    }
    
    void Caller2(int n, int (*ptr)())    //指向函數的指針作函數參數,這裏第一個參數是為指向函數的指針服務的,
    
    {                                                   //不能寫成void Caller2(int (*ptr)(int n)),這樣的定義語法錯誤。
    
    (*ptr)(n);
    
    return;
    
    }
    
    int main()
    
    {
    
    printf(“************************\n”);
    
    Caller1(Test1); //相當於調用Test2();
    
    printf(“&&&&&&************************\n”);
    
    Caller2(30, Test2); //相當於調用Test2(30);
    
    return 0;
    
    }
    
    以上通過將回調函數的地址傳給調用者從而實現調用,但是需要注意的是帶參回調函數的用法。要實現回調,必須首先定義函數指針。函數指針的定義這裏稍微提一下。比如:
    
    int (*ptr)(); 這裏ptr是一個函數指針,其中(*ptr)的括號不能省略,因為括號的優先級高於星號,那樣就成了一個返回類型為整型的函數聲明了

最後更新:2017-04-02 15:15:00

  上一篇:go HDU2454 圖的基本性質
  下一篇:go Android教父高煥堂:開源隻是手段,開放才是目的