最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C/C++ 基礎 之回調(diào)函數(shù)示例詳解

 更新時間:2025年04月29日 08:50:17   作者:GalaxyPokemon  
這篇文章主要介紹了C/C++ 基礎 之回調(diào)函數(shù)示例詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧

前言

在寫項目的時候,對于回調(diào)函數(shù)一知半解,這次將重新學習一下,重新理解一下 回調(diào)函數(shù) 的魅力所在

回調(diào)函數(shù)預備知識

在講回調(diào)函數(shù) 回調(diào)函數(shù) 回調(diào)函數(shù)之前,我們需要了解函數(shù)指針

我們都知道,C語言的靈魂是指針,我們經(jīng)常使用整型指針,字符串指針,結構體指針等

函數(shù)指針

int *p1;  // p1是一個指向整數(shù)(int)類型的指針變量,可以存儲一個int類型數(shù)據(jù)的地址
char *p2; // p2是一個指向字符(char)類型的指針變量,可以存儲一個char類型數(shù)據(jù)的地址
STRUCT *p3; // p3是一個指向結構體類型STRUCT的指針變量,STRUCT是我們定義的結構體類型

但是好像我們一般很少使用函數(shù)指針,我們一般使用函數(shù)都是直接使用函數(shù)調(diào)用

下面我們來了解一下函數(shù)指針的概念和使用方法。

什么是函數(shù)指針

函數(shù)指針也是個指針,但是和通常的指針不一樣,通常的指針指向的是整型、字符型或數(shù)組等變量

函數(shù)指針,指向的是函數(shù)

函數(shù)指針的語法

返回類型 (*指針變量名)(參數(shù)類型列表);
  • 返回類型: 函數(shù)返回的數(shù)據(jù)類型(如 int double void 等)。
  • 指針變量名: 你給這個函數(shù)指針起的名字。
  • 參數(shù)類型列表: 函數(shù)接受的參數(shù)類型(如果沒有參數(shù),可以留空或?qū)?void )。

這里需要注意的是(*指針變量名)兩端的括號不能省略,括號改變了運算符的優(yōu)先級。如果省略了括號,就不是定義函數(shù)指針。而是一個函數(shù)聲明了,即聲明了一個返回值類型為指針型的函數(shù)。

那么怎么判斷一個指針變量是指向變量的還是指向函數(shù)呢?

  • 首先看變量名前面有沒有 “*,如果有 “*” 說明是指針變量;
  • 其次看變量名有沒有帶 (),如果有就是指向函數(shù)的指針變量,即函數(shù)指針,如果沒有就是指向變量的指針變量。

最后需要注意的是:指向函數(shù)的指針變量沒有 ++ 和 – 運算。

一般為了方便使用,我們會選擇用typedef進行函數(shù)指針類型的別名定義

// 定義一個函數(shù)指針類型 別名為:Fun1,它指向返回 int 類型、接受一個 int 參數(shù)的函數(shù)
typedef int (*Fun1)(int);
// 定義一個函數(shù)指針類型 別名為:Fun2,它指向返回 int 類型、接受兩個參數(shù)(int 和 int)的函數(shù)
typedef int (*Fun2)(int, int);
// 定義一個函數(shù)指針類型 別名為:Fun3,它指向返回 void 類型、無參數(shù)的函數(shù)
typedef void (*Fun3)(void);
// 定義一個函數(shù)指針類型 別名為:Fun4,它指向返回 void* 類型、接受一個 void* 參數(shù)的函數(shù)
typedef void* (*Fun4)(void*);

為什么要使用typedef呢?

如何用函數(shù)指針調(diào)用函數(shù)

舉個例子

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

賦值時函數(shù) Func 不帶括號,也不帶參數(shù)。由于函數(shù)名 Func 代表函數(shù)的首地址因此經(jīng)過賦值以后,指針變量 p 就指向函數(shù) Func() 代碼的首地址了。

下面來寫一個程序,看了這個程序你們就明白函數(shù)指針怎么使用了:

特別注意的是,因為函數(shù)名本身就可以表示該函數(shù)地址(指針),因此在獲取函數(shù)指針時,可以直接用函數(shù)名,也可以用&取函數(shù)的地址。

函數(shù)指針作為函數(shù)的參數(shù)

 我們見過,函數(shù)的形參是指針的

// 函數(shù)接受一個整數(shù)指針作為參數(shù),并修改該值
void modifyValue(int *ptr) {
    *ptr = 20;  // 修改指針指向的值
}

那么函數(shù)指針作為指針,肯定也能放到函數(shù)的形參中的

#include <stdio.h>
// 定義一個函數(shù)類型:別名為operation,返回類型是int,參數(shù)類型是int和int
typedef int (*operation)(int, int);
// 一個加法函數(shù)
int add(int a, int b) {
    return a + b;
}
// 一個減法函數(shù)
int sub(int a, int b) {
    return a - b;
}
// 函數(shù) modifyValue 接受一個函數(shù)指針作為參數(shù),并調(diào)用它
void modifyValue(int *ptr, operation op) {
    *ptr = op(*ptr, 5);  // 使用傳入的函數(shù)指針 op 來修改 ptr 指向的值
}
int main() {
    int num = 10;
    printf("Before: %d\n", num);  // 輸出修改前的值
    // 傳遞加法函數(shù)的指針
    modifyValue(&num, add);
    printf("After add: %d\n", num);  // 輸出加法操作后的值
    // 傳遞減法函數(shù)的指針
    modifyValue(&num, sub);
    printf("After sub: %d\n", num);  // 輸出減法操作后的值
    return 0;
}

運行結果

為什么函數(shù)指針我們用的是別名operation,在下面調(diào)用modifyValue的時候,直接傳入add,sub就能識別了呢?

在C語言中,函數(shù)名(如add或sub)在沒有括號時會自動轉(zhuǎn)換為指向該函數(shù)的指針。這與operation類型 的期望使用一個函數(shù)指針相匹配。

函數(shù)指針作為函數(shù)返回類型

有了上面的基礎,要寫出返回類型為函數(shù)指針的函數(shù)應該不難了,下面這個例子就是返回類型為函數(shù)指針的函數(shù):

void (* func5(int, int, float ))(int, int)
{
    ...
}

在這里, func5 以 (int, int, float) 為參數(shù),其返回類型為 void (\*)(int, int) 。 

函數(shù)指針數(shù)組

在開始講解回調(diào)函數(shù)前,最后介紹一下函數(shù)指針數(shù)組。既然函數(shù)指針也是指針,那我們就可以用數(shù)組來存放函數(shù)指針。下面我們看一個函數(shù)指針數(shù)組的例子:

/* 方法1 */
void (*func_array_1[5])(int, int, float);
/* 方法2 */
typedef void (*p_func_array)(int, int, float);
p_func_array func_array_2[5];

回調(diào)函數(shù)

什么是回調(diào)函數(shù)

我們先來看看百度百科是如何定義回調(diào)函數(shù)的:

回調(diào)函數(shù)就是一個通過函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù),當這個指針被用來調(diào)用其所指向的函數(shù)時,我們就說這是回調(diào)函數(shù)。回調(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的,用于對該事件或條件進行響應。

這段話比較長,也比較繞口。下面我通過一幅圖來說明什么是回調(diào):

假設我們要使用一個排序函數(shù)來對數(shù)組進行排序,那么在 主程序(Main program) 中,我們先通過庫,選擇一個 庫排序函數(shù)(Library function)。但排序算法有很多,有冒泡排序,選擇排序,快速排序,歸并排序。同時,我們也可能需要對特殊的對象進行排序,比如特定的結構體等。庫函數(shù)會根據(jù)我們的需要選擇一種排序算法,然后調(diào)用實現(xiàn)該算法的函數(shù)來完成排序工作。這個被調(diào)用的排序函數(shù)就是回調(diào)函數(shù)(Callback function)。

結合這幅圖和上面對回調(diào)函數(shù)的解釋,我們可以發(fā)現(xiàn),要實現(xiàn)回調(diào)函數(shù),最關鍵的一點就是要將函數(shù)的指針傳遞給一個函數(shù)(上圖中是庫函數(shù)),然后這個函數(shù)就可以通過這個指針來調(diào)用回調(diào)函數(shù)了。注意,回調(diào)函數(shù)并不是C語言特有的,幾乎任何語言都有回調(diào)函數(shù)。在C語言中,我們通過使用函數(shù)指針來實現(xiàn)回調(diào)函數(shù)。

總結:一段可執(zhí)行的代碼(函數(shù))像參數(shù)傳遞那樣傳給其他代碼,而這段代碼會在某個時刻被調(diào)用執(zhí)行,這就叫 回調(diào) 。如果代碼立即被執(zhí)行就稱為同步回調(diào),如果過后再執(zhí)行,則稱之為異步回調(diào)

回調(diào)函數(shù) 就是一個通過函數(shù)指針調(diào)用的函數(shù)如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個函數(shù),當這個指針被用來調(diào)用其所指向的函數(shù)時,我們就說這是 回調(diào)函數(shù) 。

回調(diào)函數(shù)不是由該函數(shù)的實現(xiàn)方直接調(diào)用而是在特定的事件或條件發(fā)生時由另外的一方調(diào)用的,用于對該事件或條件進行響應。

為什么要用回調(diào)函數(shù)

因為可以把調(diào)用者與被調(diào)用者分開,所以調(diào)用者不關心誰是被調(diào)用者。它只需知道存在一個具有特定原型和限制條件的被調(diào)用函數(shù)。

簡而言之,回調(diào)函數(shù)就是允許用戶把需要調(diào)用的方法的指針作為參數(shù)傳遞給一個函數(shù),以便該函數(shù)在處理相似事件的時候可以靈活的使用不同的方法。

int Callback()    ///< 回調(diào)函數(shù)
{
    // TODO
    return 0;
}
int main()     ///<  主函數(shù)
{
    // TODO
    Library(Callback);  ///< 庫函數(shù)通過函數(shù)指針進行回調(diào)
    // TODO
    return 0;
}

回調(diào)似乎只是函數(shù)間的調(diào)用,和普通函數(shù)調(diào)用沒啥區(qū)別。

但仔細看,可以發(fā)現(xiàn)兩者之間的一個關鍵的不同:在回調(diào)中,主程序把回調(diào)函數(shù)像參數(shù)一樣傳入庫函數(shù)。

這樣一來,只要我們改變傳進庫函數(shù)的參數(shù),就可以實現(xiàn)不同的功能,這樣有沒有覺得很靈活?并且當庫函數(shù)很復雜或者不可見的時候利用回調(diào)函數(shù)就顯得十分優(yōu)秀。如果還不明白。看一下下面的例子就會恍然大悟了

怎么使用回調(diào)函數(shù)

int Callback_1(int a)   //回調(diào)函數(shù)1
{
    cout << "Hello, this is Callback_1。" << "a=" << a << endl;
    return 0;
}
int Callback_2(int b)  //回調(diào)函數(shù)2
{
    cout << "Hello, this is Callback_2。" << "b=" << b << endl;
    return 0;
}
int Callback_3(int c)   //回調(diào)函數(shù)3
{
    cout << "Hello, this is Callback_3。" << "c=" << c << endl;
    return 0;
}
int Handle(int x, int (*Callback)(int x))
{
	Callback(x); 
    return 0;
}
int main()
{
    Handle(10, Callback_1);
    Handle(20, Callback_2);
    Handle(30, Callback_3);
	return 0;
}

可能同學會有一個疑問:Callback(x); 這里就一個函數(shù)是怎么做到識別Callback_1 2 3的呢?

 Handle(10, Callback_1);  Handle(20, Callback_2);  Handle(30, Callback_3);本質(zhì)上是把Callback_1 2 3函數(shù)的地址傳給Handle函數(shù)Handle函數(shù)里的Callback(x); 它存儲的是具體回調(diào)函數(shù)的內(nèi)存地址,比如說你傳入的是 Handle(10, Callback_1);,Callback存儲的是Callback_1的地址,存儲的x變量是10,它就會找到Callback_1并且把10傳給它

下面是一個四則運算的簡單回調(diào)函數(shù)例子:

typedef float (*Operation)(float, float);
float ADD(float a, float b)
{
    cout << "a+b=" << a + b << endl;
    return a + b;
}
float SUB(float a, float b)
{
    cout << "a-b=" << a - b << endl;
    return a - b;
}
float MUL(float a, float b)
{
    cout << "a*b=" << a * b << endl;
    return a * b;
}
float DIV(float a, float b)
{
    if (b == 0) {
        printf("Error: Division by zero!\n");
        return 0;
    }
    cout << "a/b=" << a / b << endl;
    return a / b;
}
float add_sub_mul_div(float a, float b, Operation op)
{
    op(a, b);
    return 0;
}
int main()
{
    add_sub_mul_div(1.1, 2.2, ADD);
    add_sub_mul_div(1.1, 2.2, SUB);
    add_sub_mul_div(1.1, 2.2, MUL);
    add_sub_mul_div(1.1, 2.2, DIV);
    return 0;
}

總結

這下對于回調(diào)函數(shù)是更加理解了,希望各位在今后的學習中能夠看見回調(diào)函數(shù)不再迷惑!

到此這篇關于C/C++ 基礎 之回調(diào)函數(shù)示例詳解的文章就介紹到這了,更多相關c++ 回調(diào)函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Qt模仿Windows文件夾縮略圖的三種實現(xiàn)方式

    Qt模仿Windows文件夾縮略圖的三種實現(xiàn)方式

    本文講的不是簡單的model/view或者widget的或者QML的基礎框架實現(xiàn),而是在這些框架之上的肉(文件夾縮略圖)的效果實現(xiàn),本文將以QWidget、Qt Quick(QML)、以及QGraph三種實現(xiàn)方式來講解,如何做出和Windows類似的縮略圖,需要的朋友可以參考下
    2024-04-04
  • C語言實現(xiàn)三子棋源代碼

    C語言實現(xiàn)三子棋源代碼

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)三子棋源代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • c++動態(tài)庫調(diào)用的實現(xiàn)

    c++動態(tài)庫調(diào)用的實現(xiàn)

    本文主要介紹了c++動態(tài)庫調(diào)用的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • C/C++中指針的深入理解

    C/C++中指針的深入理解

    指針在 C\C++ 語言中是很重要的內(nèi)容,并且和指針有關的內(nèi)容一向令初學者頭大,這篇文章主要給大家介紹了關于C/C++中指針的相關資料,需要的朋友可以參考下
    2021-07-07
  • C語言利用EasyX實現(xiàn)繪制足球圖案

    C語言利用EasyX實現(xiàn)繪制足球圖案

    這篇文章主要為大家詳細介紹了C語言如何利用EasyX繪圖庫實現(xiàn)繪制一個簡單的足球圖案,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2022-11-11
  • C語言實現(xiàn)紙牌游戲之小貓釣魚算法

    C語言實現(xiàn)紙牌游戲之小貓釣魚算法

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)紙牌游戲之小貓釣魚算法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • C++實現(xiàn)Dijkstra(迪杰斯特拉)算法

    C++實現(xiàn)Dijkstra(迪杰斯特拉)算法

    這篇文章主要為大家詳細介紹了C++實現(xiàn)Dijkstra(迪杰斯特拉)算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C語言Make命令用法講解

    C語言Make命令用法講解

    本文詳細講解了C語言Make命令用法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • 基于C語言實現(xiàn)靜態(tài)通訊錄的示例代碼

    基于C語言實現(xiàn)靜態(tài)通訊錄的示例代碼

    這篇文章主要為大家詳細介紹了如何利用C語言實現(xiàn)一個簡單的靜態(tài)通訊錄,文中的示例代碼講解詳細,對我們學習C語言有一定幫助,需要的可以參考一下
    2022-07-07
  • C++利用隨機策略實現(xiàn)優(yōu)化二叉樹操作效率

    C++利用隨機策略實現(xiàn)優(yōu)化二叉樹操作效率

    這篇文章中我們主要來詳細探討隨機化二叉搜索樹的基本思想、實現(xiàn)方法,以及如何在C++中應用這些策略來優(yōu)化我們的數(shù)據(jù)結構,感興趣的可以了解下
    2024-02-02

最新評論

什邡市| 锦州市| 嫩江县| 无极县| 斗六市| 宾阳县| 尤溪县| 望城县| 霞浦县| 慈利县| 奈曼旗| 通辽市| 松阳县| 汕尾市| 叶城县| 固安县| 铁岭市| 宁都县| 东平县| 锦屏县| 商城县| 白水县| 晴隆县| 资兴市| 修水县| 龙山县| 璧山县| 高安市| 廊坊市| 通渭县| 波密县| 宣城市| 伽师县| 汝阳县| 偃师市| SHOW| 新邵县| 沁阳市| 南木林县| 新化县| 陵水|