C語言——深入淺出回撥函式
一、背景
從軟體工程的角度判斷軟體設計好壞的標準就是高內聚低耦合。目的是使程式模組的可重用性、移植性大大增強。通常程式結構中各模組的內聚程度越高,模組間的耦合程度就越低。內聚是從功能角度度量模組內的聯絡,好的內聚模組應當恰好做一件事,它描述的是模組內的功能聯絡;耦合是軟體結構中各模組之間相互連線的一種度量,耦合強弱取決於模組間介面的複雜程度、進入或訪問一個模組的點以及通過介面的資料。要實現高內聚低耦合,回撥函式則是不得不提的內容。
二、函式指標
定義:存放函式空間首地址的指標變數。
編譯器在編譯函式的時候,會為函式分配儲存空間。有了儲存空間後,我們可以通過獲取該儲存空間的首地址從而去獲取到我們的函式片段。依靠指標可以完成對函式程式碼片段地址的定位,指向該首地址的指標變數,就叫做函式指標。(本質上函式名也是指向首地址的)
如下為函式指標的定義示例之一:
返回型別(* 指標變數名稱)(引數)
int (* ptFun)(int, int)
三、回撥函式
定義:回撥函式就是一個通過函式指標進行呼叫的函式(其實回撥函式只是一個功能函式而已)。當你把函式名(即函式的地址)作為引數傳遞給另外一個函式(即註冊函式),向註冊函式進行回撥函式的註冊時,註冊函式通過函式指標來呼叫該函式指標所指向的函式時,我們就說這是在回撥函式,被函式指標指向的函式即稱為回撥函式(回撥函式其實只是一個名字而已,不需深究,叫被調函式也可以)。
四、回撥函式作用
為了實現軟體的高內聚低耦合,出現了各種各樣的方法。而回調函式的就是其中之一,恰好為降低模組間的耦合度起到了很好的作用。為什麼回撥函式可以實現降低模組間耦合度的作用呢?回撥函式可以統一呼叫不同的被呼叫函式的介面,針對不同的回撥函式,如void showPstSeq(int * )和void showRevSeq(int *)可以封裝成同一函式介面void (*Callback)(int *),下面我們通過一個例子來分析一下。
五、回撥函式呼叫示例
#include <stdio.h>
//陣列長度
#define LEN 10
//定義回撥函式指標
typedef void(*CallBack)(int *);
//函式原型宣告
void showPstSeq(int *);
void showRevSeq(int *data);
void showArray(int *data, CallBack callback);
int main()
{
int data[LEN] = {0,1,2,3,4,5,6,7,8,9};
showArray(data, showPstSeq); //回撥函式showPstSeq向註冊函式進行註冊,實現正序輸出陣列元素
showArray(data, showRevSeq); //回撥函式showRevSeq向註冊函式進行註冊,實現逆序輸出陣列元素
return 0;
}
//回撥函式,正序輸出陣列元素
void showPstSeq(int *data)
{
printf("正序輸出陣列:");
int i;
for(i=0; i<LEN; i++)
{
printf("%d ",data[i]);
}
printf("\n");
}
//回撥函式,逆序輸出陣列元素
void showRevSeq(int *data)
{
printf("逆序輸出陣列:");
int i;
for(i=LEN-1; i>=0; i--)
{
printf("%d ",data[i]);
}
printf("\n");
}
//註冊函式,其入參為函式指標(回撥函式指標)
void showArray(int *data, CallBack callback)
{
callback(data); //呼叫回撥函式
return;
}
輸出結果:

六、總結
上面例子中,同一個註冊函式既能實現正序輸出陣列元素,又能夠逆序輸出陣列元素,無需使用複雜的流程進行處理,只需要傳遞不同的實參即可實現,同時擴充套件性極好,如果需要增加其他新的顯示陣列元素的方式,只需要增加新的回撥函式即可,無需更改註冊函式內部實現邏輯。
