天天看點

回調函數-C/C++

   回調函數,具體是什麼呢,可能部分朋友 還不太清楚,這裡我分享下自己的了解,如有錯誤,敬請指教  感謝

   什麼是回調函數?--------- 被動調用的函數 or  已經離職老久的老哥寫的代碼子產品,可以調用你現在寫的函數。

       比較抽象對吧  ,我也覺得 ,可能是自己的底蘊不夠,不能清晰表達出來我的了解,請看下面的内容對照了解吧。

      我們最常寫的函數,是為了完成某個功能 而寫的, 然後在需要的時候 直接用函數名+()進行調用,得到傳回值。

      回調函數會稍稍有點差別,在說這個之前呢,我們先了解下回調函數重要的一個前置知識點:函數指針

      指針 大家都比較熟悉的吧

      int*,    char* ,   char**,...這些屬于基礎類型的指針,函數指針呢 故名思意就是 指向函數的指針

      函數的組成:傳回值類型   函數名稱(函數參數){ 

                                   函數體

                             }

      如果要定義一個函數指針,我們需要   傳回值類型    函數名稱  和  函數參數, 最重要的是 傳回值類型和函數參數,我們看一個

最簡單的函數指針

     void print(void){

             printf("我挺suai!\n");

    }

這是個非常非常精煉精簡的函數,尤其那個printf  ,   這裡就有一個函數指針,大家能分析分析是哪個不,

print,對 這個函數名 就是一個函數指針,這個函數指針的 傳回值類型:void ,  參數類型:void

但是 這個函數指針屬于常量,為什麼呢,因為這個函數是已經定義了,是以,我們不能将print再指向其他的同類型函數了,會報

"表達式必須是可修改的左值 "的錯誤, 那麼我們怎麼定義可以像基礎類型指針一樣 可以指來指去 迷糊人呢

其實很簡單-------------函數聲明 加個 *,我們隻聲明不定義,這樣就可以指來指去了,當然了 ,要求 傳回值類型和函數參數類型、個數必須一緻的這種形式的函數。

如  : void (*Func)(void);

這裡 Func 可以指向任意一個  函數傳回值類型為:void   函數參數為void 的函數了,比如讓Func指向上面精煉的print函數:

     Func = print;//常量值可以指派給變量喲

這樣指派之後  Func就等價于print了,如果我們進行調用:

     Func();   //等價于   print();

大家可能要說了,如果我要用到多個這樣的指針了,咋辦 ,一個個定義? 哈哈 是可以的  推薦你一個個定義,雖然有更好更便捷的方法,可我不告訴你,hhhhhh.

     我們可以用 關鍵字  typedef  将一個函數指針重命名一個函數類型,如:

     typedef void (*pFunc)(void);

  這樣的話,我們就有一個  函數傳回值類型為:void  函數參數為:void的函數指針類型可用了

    我們可以像定義普通的變量一樣:

      pFunc pfunc1;    pFunc  pfunc2;

     pfunc1 = print;   pfunc2 = print

     調用時:pfunc1();     pfunc2();  print(); 這三個函數的調用是等價的

  好了,相信大家對函數指針有了初步了解了吧,接下來我們來說主題---------回調函數

  回調函數必備的一個特性:函數形參是 函數指針類型 

  大家看到有函數的函數形參是 函數指針類型的話,沒錯  這就是回調函數

  回調函數的機制: 開發者 根據 接口形參的函數指針類型  編寫相同類型的函數,将函數名作實參,傳遞給接口進行調用,

接口内部對函數指針參數傳參調用,傳遞資料,達到已經成型固定的、封裝的代碼塊,可以調用後面開發者寫的代碼,并傳遞資料出去的效果。非常實用。

   接下來給大家舉個例子:

   2000年封裝的子產品:

   typedef void (*pFunc)(int errnum,const char * info)

   void GetErrorInfo(pFunc CallBackFunc) //or   void GetLogInfo(void (*CallBackFunc)(int errnum,const char * info))

  {

     int errnum = 0;

     char errstr[128] = "hello  我錯了  我驕傲";

      ..

      ..

      if (err){

          CallBackFunc(errnum, errstr);

          return;

      } 

}

2020年寫的功能:

   void ErrorInfo(int errnum,const char * info)

{

       printf("errnum:%d\t errorInfo:%s\n", errnum, info);

       //寫入日志 or  發送給日志伺服器

}

//業務功能代碼

void mainFunc(){

..

GetErrorInfo(ErrorInfo)

..

}

我們新寫的函數被已經封裝的接口進行了調用,這就是回調函數,回調函數具體有啥用呢,大家可以看下win32建立windows視窗的程式,消息回調函數,windows最最重要的機制 消息循環機制 就是用了回調函數,通過回調函數  我們可以将協定号和對應 的函數指針用map或者其他的容器進行注冊,然後建立一個消息循環,收到消息 解析協定号,在容器中找到對應的協定号,通過指針函數調用相應的處理函數,這個後面有時間我寫下示範消息循環機制的代碼,這次的回調函數就是上面這樣了,如果你還不太明白的話,那應該是我還沒表述明白,可以将疑問評論,我看到了,會一起探讨下。