回調函數是利用函數指針做函數參數,實現的一種調用機制,具體任務的實現者,可以不知道什麼時候被調用。
回調機制原理:
當具體事件發生時,調用者通過函數指針調用具體函數。
回調機制的将調用者和被調函數分開,兩者互不依賴。
任務的實現和任務的調用可以實現松耦合(提前進行接口的封裝和設計)。
看以下實例:
#include <iostream>
using namespace std;
int add(int a, int b);
void libfun(int (*pDis)(int a, int b));
int main(void)
{
int (*pfun)(int a, int b);
pfun = add;
libfun(pfun);
return 0;
}
int add(int a, int b)
{
return a b;
}
int minus(int a, int b)
{
return a - b;
}
void libfun(int (*pDis)(int a, int b))
{
int a, b;
a = 1;
b = 2;
int c = add(a,b); //直接調用add函數
c = pDis(a, b);
printf("%d", c); //通過函數指針做函數參數,間接調用add函數
//思考這樣寫pDis(a, b)有什麼好處?
}
假設要實現減法呢?現在這幾個函數是在同一個文件當中,可以直接在
int libfun(int (*pDis)(int a, int b))
中修改,假設libfunc()是一個庫中的函數,你就隻能使用函數指針的回調機制了,通過函數指針參數将外部函數地址傳入來實現調用。
當然,函數 add()或minus() 的代碼作了修改,也不必改動庫的代碼,就可以正常實現調用。
最重要的是,即使将add換成另一個函數,也不需要修改libfun(),隻需在調用時将其函數指針參數使用不同的實參就行了。這就是低耦合的思想,便于程序的維護和升級。
再看一個例子:
#include <iostream>
using namespace std;
bool lesser(int a, int b);
bool greater(int a, int b);
void libSwap(bool (*pDis)(int a, int b)); // 通過函數直接來調用lesser()或greater()函數
void libSwap(); // 直接在函數體内調用lesser()或greater()函數
int main(void)
{
libSwap(lesser);
//libSwap(greater);
libSwap();
while(1);
return 0;
}
bool greater(int a, int b)
{
return a > b;
}
bool lesser(int a, int b)
{
return a < b;
}
void libSwap(bool (*pDis)(int a, int b)) //通過函數指針做函數參數,間接調用add函數
{
int a = 5, b = 7;
if(pDis(a, b))
{
int tmp = a;
a = b;
b = tmp;
}
cout<<a<<" "<<b<<endl;
}
void libSwap() //直接在函數體内調用lesser()或greater()函數
{
int a = 5, b = 7;
if(lesser(a,b))
//if(greater(a,b))
{
int tmp = a;
a = b;
b = tmp;
}
cout<<a<<" "<<b<<endl;
}
上列假設libSwap()是庫函數。庫使用者在main()中調用
void libSwap(bool (*pDis)(int a, int b))
此函數有一個函數指針,需要提供函數供其使用,此時庫使用者編寫greater()、lesser(),這兩個函數庫使用者并不直接調用,而是由libSwap()去調用。greater()、lesser()這種函數就稱為回調函數,整個設計機制就是回調函數調用機制。
所謂回調,就是客戶程序C調用服務程序S中的某個函數s(),然後S又在某個時候反過來調用C中的某個函數c(),對于C來說,這個c()便叫做回調函數。例如Win32下的窗口過程函數就是一個典型的回調函數。
一般說來,C不會自己調用c(),c()提供c()的目的就是讓S來調用它,而且是C不得不提供。由于S并不知道C提供的c()叫甚名誰,所以S會約定c()的接口規範(函數原型),然後由C提前通過S的一個函數r()告訴S自己将要使用c()函數,這個過程稱為回調函數的注冊,R稱為注冊函數。
在框架中,定義函數指針,相當于提前指定了一套協議接口。
對于排序函數,如果想用同一個排序函數來實現升序或降序排列,調用時不修改此函數的排序邏輯,可以考慮使用函數指針來調用回調函數,而stdlib.h庫中的qsort()函數即是如此來實現這一邏輯的:
#include <stdio.h>
#include <stdlib.h>
int compare(int a, int b) // 用于bubbleSort()的回調函數
{
return a-b;
//return b-a;
}
int cmp(const void* a, const void* b) // 用于庫函數qsort()
{
return (*((int*)a) - *((int*)b));
//return (*((int*)b) - *((int*)a));
}
void bubbleSort(int arr[], int n, int (*compare)(int,int))
{ // 隻需更改函數指針指向的回調函數,即可實現升序或降序排列
for(int i=0; i<n; i )
for(int j=0;j<n-i-1; j )
if(compare(arr[j],arr[j 1])>0)
{
int tmp = arr[j];
arr[j] = arr[j 1];
arr[j 1] = tmp;
}
}
void arrOutput(int arr[], int n)
{
for(int i=0;i<n; i )
printf("%d ",arr[i]);
printf("\n");
}
int main()
{
int arr[] = {3,2,1,5,4};
int n = sizeof(arr)/sizeof(arr[0]);
bubbleSort(arr,n,compare);
arrOutput(arr,n);
int arr2[] = {3,2,1,5,4};
qsort(arr2,n,sizeof(int),cmp);
arrOutput(arr2,n);
while(1);
return 0;
}
/*
1 2 3 4 5
1 2 3 4 5
*/
-End-
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!