C語言_鉤子函數

目錄

1.引言

2.變量指針

3.函數指針

4.帶參數的鉤子函數


1.引言

鉤子函數、回調函數、註冊函數,掛鉤子這些我們代碼中經常涉及到的東西,是否已經困擾你很久了?它們究竟是怎麼回事,究竟怎麼用?下面我來爲你一一解答。

什麼是鉤子函數?

鉤子函數也叫回調函數,是通過函數指針來實現的,那我們來看看什麼是函數指針。

2.變量指針

首先看看以下例子:

我們可以讓指針p先後指向a, b,這樣,p就先後代表了不同變量的地址

p = &a;

p = &b;

3.函數指針

同樣地,函數的指針可以指向不同的函數,從而完成不同的功能。

例如,定義函數指針:

int (* g_pFun) (int x, int y);

有兩個函數:

/*返回兩個參數中的最大值*/

int Max(int x, int y)

{

}

/*返回兩個參數中的最小值*/

int Min(int x, int y)

{

}

int main(int argc, char* argv[])

{

    int r;

/*我們讓函數指針先後指向不同的函數*/   

int a = 10;

    int b = 15;

    g_pFun = Max;

    r= g_pFun(a, b); /*相當於執行函數Max*/

    printf("%d\n", r);

    g_pFun = Min;

    r= g_pFun(a, b); /*相當於執行函數Min*/

    printf("%d\n", r);

    return 0;

}

分別輸出:15

          10

這樣,同樣調用g_fun ,兩次卻完成不同的功能,神奇吧?這就是函數指針的妙用。

Max,Min函數就是鉤子函數了,把函數指針g_pFun指向函數Max,Min的過程,就是“掛鉤子”的過程,把鉤子函數“掛”到函數指針上,很形象。

4.鉤子函數作用

有人可能有疑問,那麼這裏爲什麼不直接調用Max和Min函數呢?

這是因爲,我們在寫main函數的時候,可能還不知道它會完成什麼功能,這時候留下函數指針作爲接口,可以掛上不同的函數完成不同的功能,究竟執行什麼功能由鉤子函數的編寫者完成。

5.鉤子函數使用

那我們平時怎麼用的呢?

在我們的代碼中,常常把掛鉤子的過程叫做註冊,會提供一個註冊函數,讓使用者把自己編寫的鉤子函數掛在已經聲明的函數指針上,這個註冊函數的參數就是我們的函數指針了,比如,我們可以給剛纔的函數指針提供一個註冊函數:

int RegFun( int (* pFun)(int x, int y) ) /*註冊函數的參數是函數指針*/

{

    g_pFun = pFun;

    return 0;

}

調用RegFun(Max)和RegFun(Min),就可以把鉤子函數掛上去了。

注意:爲了便於使用,函數指針往往被聲明爲全局變量,這也是剛纔把函數指針的名字命名爲g_pFun的原因。

下面我們來進行一下實戰演習,比如,平臺部分要執行某一個操作,但是具體的操作還不確定,我們完成這樣的代碼:

int (* g_pFun) (int x, int y);  /*函數指針*/

int Plat()

{

     int r;

     int a = 10;

     int b = 15;

     r= g_pFun(a, b); /*這裏要做一個操作,但是具體的操作還不確定*/

     printf("%d\n", r);

     return 0;

}

另外,平臺部分再提供一個註冊函數:

int RegFun(int (* pFun)(int x, int y))

{

       g_pFun = pFun;

       return 0;

}

 

應用模塊完成具體的函數的功能:

int Max(int x, int y)
{
    if(x>y)
        return x;
    else
        return y;
}

int Min(int x, int y)
{
    if(x<y)
       return x;
    else
       return y;

}

因爲應用模塊無法修改平臺的代碼,只能調用平臺提供的註冊函數:

如果應用模塊註冊:

 RegFun(Max);

則運行 main 函數時,輸出:15

如果應用模塊註冊:

RegFun(Min)

運行 main 函數時,輸出:10

這樣,平臺部分無需修改任何代碼,只是應用模塊註冊了不同的鉤子函數,就能夠完成不同的功能,這就是鉤子函數的妙用。
————————————————
版權聲明:本文爲CSDN博主「DyLan985」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/sunstars2009918/article/details/39340449

6.帶參數的鉤子函數

眼尖的朋友可能發現了,前面的例子裏面回調函數是沒有參數的,那麼我們能不能回調那些帶參數的函數呢?答案是肯定的。那麼怎麼調用呢?

#include<stdio.h>

int Callback_1(int x) // Callback Function 1

{

printf("Hello, this is Callback_1: x = %d ", x);

return 0;

}

int Callback_2(int x) // Callback Function 2

{

printf("Hello, this is Callback_2: x = %d ", x);

return 0;

}

int Callback_3(int x) // Callback Function 3

{

printf("Hello, this is Callback_3: x = %d ", x);

return 0;

}

int Handle(int y, int (*Callback)(int))

{

printf("Entering Handle Function. ");

Callback(y);

printf("Leaving Handle Function. ");

}

int main()

{

int a = 2;

int b = 4;

int c = 6;

printf("Entering Main Function. ");

Handle(a, Callback_1);

Handle(b, Callback_2);

Handle(c, Callback_3);

printf("Leaving Main Function. ");

return 0;

}

運行結果:

Entering Main Function.

Entering Handle Function.

Hello, this is Callback_1: x = 2

Leaving Handle Function.

Entering Handle Function.

Hello, this is Callback_2: x = 4

Leaving Handle Function.

Entering Handle Function.

Hello, this is Callback_3: x = 6

Leaving Handle Function.

Leaving Main Function.

可以看到,並不是直接把int Handle(int (*Callback)()) 改成 int Handle(int (*Callback)(int)) 就可以的,而是通過另外增加一個參數來保存回調函數的參數值,像這裏 int Handle(int y, int (*Callback)(int)) 的參數 y。同理,可以使用多個參數的回調函數。

轉自https://www.cnblogs.com/jiangzhaowei/p/9129105.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章