色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一文詳解C/C++回調函數

zzw_111_bit ? 來源:zzw_111_bit ? 作者:zzw_111_bit ? 2023-02-12 09:20 ? 次閱讀

C/C++回調函數

首先看一下回調函數的官方解釋:回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用于對該事件或條件進行響應。這段解釋比較官方。個人可以簡單的理解為:**一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用于對該事件或條件進行響應。**如果代碼立即被執行就稱為同步回調,如果過后再執行,則稱之為異步回調。

入門案例

int Callback_1(int a)   ///< 回調函數1
{
    printf("Hello, this is Callback_1: a = %d ", a);
    return 0;
}

int Callback_2(int b)  ///< 回調函數2
{
    printf("Hello, this is Callback_2: b = %d ", b);
    return 0;
}

int Callback_3(int c)   ///< 回調函數3
{
    printf("Hello, this is Callback_3: c = %d ", c);
    return 0;
}

int Handle(int x, int (*Callback)(int)) ///< 注意這里用到的函數指針定義
{
    Callback(x);
}

int main()
{
    Handle(4, Callback_1);
    Handle(5, Callback_2);
    Handle(6, Callback_3);
    return 0;
}

在這個入門案例中,Callback_1、2、3就是回調函數,handle函數的第二個參數就是函數指針,也就是通過函數指針來調用。純C語言通過函數指針來進行回調函數的調用,C++則可以通過引用、Lambda等多種方式來進行,下面進行具體的介紹。

函數指針

首先函數指針也是一種指針,只不過指向的是函數(C語言中沒有對象)。然后通過這個指針就可以調用。

int Func(int x);   /*聲明一個函數*/
int (*p) (int x);  /*定義一個函數指針*/
p = Func;          /*將Func函數的首地址賦給指針變量p*/
p = &Func;          /*將Func函數的首地址賦給指針變量p*/

經過上述后,指針變量 p 就指向函數 Func() 代碼的首地址了。下面看一個具體的例子。

int Max(int x, int y)  //定義Max函數
{
    if (x > y){
        return x;
    }else{
      return y;
    }
}
int main()
{
  int(*p)(int, int);  //定義一個函數指針
  p = Max;  //把函數Max賦給指針變量p, 使p指向Max函數
  int c= (*p)(1,2);//通過函數指針調用Max函數
  printf("%d",c);  
  return 0;
}

p指向Max函數之后,然后用p調用Max函數,返回兩個數中的最大值。特別注意的是,因為函數名本身就可以表示該函數地址(指針),因此在獲取函數指針時,可以直接用函數名,也可以取函數的地址。

p = Max可以改成 p = &Max;

c = (*p)(a, b) 可以改成 c = p(a, b)

所以函數指針的通常寫法是

函數返回值類型 (* 指針變量名) (函數參數列表);

在這里指針變量名也可以叫做函數名,

但是通常可以用typedef進行描述

typedef 函數返回值類型 (* 指針變量名) (函數參數列表);

最后需要注意的是,指向函數的指針變量沒有 ++ 和 -- 運算。

C++類的靜態函數作為回調函數

前面函數指針的方式作為回調函數的一種方式,可以同時用于C和C++,下面介紹另外的一些方式,因為C++引入了對象的概念,可以使用類的成員和靜態函數作為回調函數。

class ProgramA {
 public:
  void FunA1() { printf("I'am ProgramA.FunA1() and be called..\\n"); }

  static void FunA2() { printf("I'am ProgramA.FunA2() and be called..\\n"); }
};
class ProgramB {
 public:
  void FunB1(void (*callback)()) {
    printf("I'am ProgramB.FunB1() and be called..\\n");
    callback();
  }
};
int main(int argc, char **argv) {
  ProgramA PA;
  PA.FunA1();

  ProgramB PB;
  PB.FunB1(ProgramA::FunA2);
}

在類B中調用類A中的靜態函數作為回調函數,從而實現了回調。但這種實現有一個很明顯的缺點:static 函數不能訪問非static 成員變量或函數,會嚴重限制回調函數可以實現的功能。

類的非靜態函數作為回調函數

這種方式比較麻煩,可以先看一下下面的例子。

class ProgramA {
 public:
  void FunA1() { printf("I'am ProgramA.FunA1() and be called..\\n"); }

  void FunA2() { printf("I'am ProgramA.FunA2() and be called..\\n"); }
};

class ProgramB {
 public:
  void FunB1(void (ProgramA::*callback)(), void *context) {
    printf("I'am ProgramB.FunB1() and be called..\\n");
    ((ProgramA *)context->*callback)();
  }
};
int main(int argc, char **argv) {
  ProgramA PA;
  PA.FunA1();

  ProgramB PB;
  PB.FunB1(&ProgramA::FunA2, &PA);  // 此處都要加&
}

功能總體與上面一個相同,但是,類的靜態函數本身不屬于該類,所以和普通函數作為回調函數類似。這種方式存在一些不足,,也就我預先還要知道回調函數所屬的類定義,當ProgramB想獨立封裝時就不好用了。(違背了一些設計模式的原則)

Lambda表達式作為回調函數

Lambda本身就是一種匿名函數,是一種函數的簡寫形式(此處參考上一篇博客Lambda表達式)

#include 
#include
void func1(int a,std::function<void(int)> func2){
  func2(a);
}
int main(int argc, char **argv) {
  auto fun3 = [](int a){
    std::cout<std::endl;
  };
  func1(3,fun3);
}

這種方式也較為簡單,但要注意在C++11版本才開始引入Lambda表達式,在一些較為老舊的編譯器上可能無法通過。

std::funtion和std::bind的使用

這種方式也是適用于C++,要引入functional的頭文件。存儲、復制、和調用操作,這些目標實體包括普通函數、Lambda表達式、函數指針、以及其它函數對象等。std::bind()函數的意義就像它的函數名一樣,是用來綁定函數調用的某些參數的。

#include 

#include  // fucntion/bind

class ProgramA {
 public:
  void FunA1() { printf("I'am ProgramA.FunA1() and be called..\\n"); }

  void FunA2() { printf("I'am ProgramA.FunA2() and be called..\\n"); }

  static void FunA3() { printf("I'am ProgramA.FunA3() and be called..\\n"); }
};

class ProgramB {
  typedef std::function<void ()> CallbackFun;
 public:
   void FunB1(CallbackFun callback) {
    printf("I'am ProgramB.FunB2() and be called..\\n");
    callback();
  }
};

void normFun() { printf("I'am normFun() and be called..\\n"); }

int main(int argc, char **argv) {
  ProgramA PA;
  PA.FunA1();

  printf("\\n");
  ProgramB PB;
  PB.FunB1(normFun);
  printf("\\n");
  PB.FunB1(ProgramA::FunA3);
  printf("\\n");
  PB.FunB1(std::bind(&ProgramA::FunA2, &PA));
}

主要看最后一行,通過std::bind函數綁定了對象與對應的函數,這種方式比上面的通過類的成員函數進行回調更為簡單方便。下面看一下如果有參數的話,需要引入占位符std::placeholders::_1來進行回調。

#include 
#include 
using namespace std;
 
int TestFunc(int a, char c, float f)
{
    cout << a << endl;
    cout << c << endl;
    cout << f << endl;
 
    return a;
}
 
int main()
{
    auto bindFunc1 = bind(TestFunc, std::placeholders::_1, 'A', 100.1);
    bindFunc1(10);
 
    cout << "=================================\\n";
 
    auto bindFunc2 = bind(TestFunc, std::placeholders::_2, std::placeholders::_1, 100.1);
    bindFunc2('B', 10);
 
    cout << "=================================\\n";
 
    auto bindFunc3 = bind(TestFunc, std::placeholders::_2, std::placeholders::_3, std::placeholders::_1);
    bindFunc3(100.1, 30, 'C');
 
    return 0;
}

上述例子中引入了占位符std::placeholders::_1,可以有多個,通過下劃線加數字來實現,從而實現有參數的回調。這個bind函數中的重載通常第一個是函數的指針,第二個是調用對象的指針,后面跟上參數占位符。
審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4327

    瀏覽量

    62571
  • 指針
    +關注

    關注

    1

    文章

    480

    瀏覽量

    70551
  • C++
    C++
    +關注

    關注

    22

    文章

    2108

    瀏覽量

    73619
  • 回調函數
    +關注

    關注

    0

    文章

    87

    瀏覽量

    11554
收藏 人收藏

    評論

    相關推薦

    詳解C語言函數指針與調函數

    在講調函數之前,我們需要了解函數指針。
    發表于 10-19 09:34 ?788次閱讀

    C語言里面的函數指針和調函數

    在講調函數之前,我們需要了解函數指針。
    發表于 12-13 10:28 ?627次閱讀

    C 語言調函數詳解

    C 語言調函數詳解什么是調
    發表于 04-08 10:36

    C/C++調函數

    C/C++調函數首先看一下回調
    發表于 02-11 15:25

    C語言調函數學習

    對指針的應用是C語言編程的精髓所在,而回調函數就是C語言里面對函數指針的高級應用。簡而言之,
    發表于 05-27 09:44 ?7204次閱讀

    C語言函數調函數

    來源:嵌入式客棧 1 什么是調函數?首先什么是調呢? 我的理解是:把段可執行的代碼像參數傳
    的頭像 發表于 09-11 09:57 ?4128次閱讀

    CC++一回事嗎

    C89,C++標準是C++99。 我們來介紹C語言和C++中那些不同的地方。 函數默認值 在
    的頭像 發表于 11-13 18:18 ?3284次閱讀

    c語言調函數的使用及實際作用詳解

    大家好,我是無際。今天給大家講下芯片/模塊廠家寫SDK必須會使用的種技術:調函數
    發表于 11-20 19:51 ?13次下載
    <b class='flag-5'>c</b>語言<b class='flag-5'>回</b><b class='flag-5'>調</b><b class='flag-5'>函數</b>的使用及實際作用<b class='flag-5'>詳解</b>

    詳解調函數的概念及使用步驟

    調函數就是個被作為參數傳遞的函數。在C語言中,
    的頭像 發表于 05-26 15:20 ?4014次閱讀

    詳解事件調VI

    通過事件調注冊函數(Register Event Callback)注冊調VI,在事件發
    的頭像 發表于 11-24 09:13 ?1907次閱讀

    介紹在C++中實現調的幾種方法

    C++中的個重要概念就是類,所以我們般想讓類的成員函數作為調
    的頭像 發表于 01-18 15:09 ?3701次閱讀

    C語言技巧之調函數

    在講調函數之前,我們需要了解函數指針。
    的頭像 發表于 04-18 11:50 ?777次閱讀

    C語言|調函數的不同用法

    調函數是個高級操作技巧,也是日常項目中常常使用到的技能。之所以說調函數是個高級操作技巧,是因
    發表于 07-10 10:34 ?1292次閱讀

    C++生成Dll與調函數測試

    描述了VS環境下,通過C++生成dll的方法,測試調函數
    的頭像 發表于 08-29 16:05 ?1607次閱讀
    <b class='flag-5'>C++</b>生成Dll與<b class='flag-5'>回</b><b class='flag-5'>調</b><b class='flag-5'>函數</b>測試

    調函數(callback)是什么?調函數的實現方法

    調函數種特殊的函數,它作為參數傳遞給另函數
    發表于 03-12 11:46 ?2903次閱讀
    主站蜘蛛池模板: 99RE6这里只有精品国产AV| 国产精选视频在线观看| 99在线观看| xxx动漫xxx在线观看| 电影 qvod| 国产亚洲精品久久777777| 精品国产国偷自产在线观看| 久久re视频这里精品09免费| 老师的脚奴| 日本不卡一二三| 亚洲2023无矿砖码砖区| 在线观看永久免费网址| 爱如潮水3免费观看日本| 国产精品99久久久久久AV下载 | 亚洲免费三级电影| 中文字幕无码一区二区免费| chinesevideos原创麻豆| 国产精品亚洲二线在线播放| 久久999视频| 琪琪电影午夜理论片77网| 香蕉97超级碰碰碰碰碰久| 欲香欲色天天综合和网| 达达兔欧美午夜国产亚洲| 国模丽丽啪啪一区二区| 免费精品国偷自产在线| 外国xxxx| 90后美女乳沟| 国产精品人妻无码久久久奥特曼 | 美女被抽插到哭内射视频免费| 青草影院内射中出高潮-百度| 羞羞答答的免费视频在线观看| 中文字幕一区二区三区在线播放| 达达兔欧美午夜国产亚洲| 久久毛片基地| 手机免费毛片| 2018三级网站免费观看| 国产精品99久久久精品无码| 男男免费看| 亚洲日韩视频免费观看| 成人精品视频99在线观看免费| 九九免费高清在线观看视频|