C++回調函數


————這篇文章會隨着學習逐步更新,同時和Java接口回調配合記錄————

回調函數

回調函數是一個時時聽到的概念,比如在windows API編程時遇到的WinProc函數,就是我們編寫而由操作系統調用的函數。現在,我們需要慢慢又詳細的記錄一下這個問題。

庫與使用者的問題

在開始之前,首先我們想像這樣一個情景,一個大型軟件公司開發一套軟件庫提供給用戶使用。在這句話中,出現兩個對立面,一個是軟件公司,一個是用戶。顯然,軟件公司實力很強大,他們強大的地方在於他們很聰明。請看下圖:

庫開發者是提供方,他們不知道用戶想做什么,庫開發者對用戶的信息是未知的,因為兩邊的人誰也沒見過誰,就像一個人在美國一個人在中國。他們聰明的地方就在於即使不知道用戶怎么操作,他們也可以用一種通用的方法來解決用戶的問題。換句話說,庫開發方不管用戶怎么折騰變化,他都能適應。這就是問題的神奇之處,當然,為了達到這種效果,必須有一種規則來約束。

規則 

現在來說規則,規則比較好理解,就是兩方達成的約束。比如甲和乙兩個人,甲對乙說,你只要提供給我一個塑料球,我都能給它塗上顏色。這里的約束是塑料球,(當然,為了簡化問題這里的約束還是比較泛泛而不嚴謹的),這個時候如果乙給他一個水晶球,或者給他一輛汽車都不行,因為已經超越了約束。所以說,庫開發者能適應用戶的各種變化就在於他也給了用戶一定的約束,是在約束之下的適應,這也是不言自明的。

代碼之下無秘密

下面一段代碼極好的解釋了上述問題:

#include <stdio.h>

typedef int student_id;
typedef int student_age;
typedef struct _Student{
    student_id id;
    student_age age;
}Student;

//類型重定義:函數指針類型
typedef bool (*pFun)(Student, Student);


//-----------------------------------------------
//冒泡排序法:能夠按AGE或ID排序,用同一個函數實現
//-----------------------------------------------
void sort(Student stu[],const int num,pFun fun)
{
    Student temp;
    
    for(int i = 0; i < num; ++i)
  {
for(int j = 0; j < num - i -1; ++j) { if((*fun)(stu[j],stu[j+1])) { temp = stu[j]; stu[j] = stu[j+1]; stu[j+1] = temp; } } } } //----------------------------------------------- //回調函數:比較年齡 //----------------------------------------------- bool CompareAge(Student stu1,Student stu2) { //更改從大到小還是從小到大的順序,只需反一下。 if(stu1.age < stu2.age) return true; return false; } //----------------------------------------------- //回調函數:比較id //----------------------------------------------- bool CompareId(Student stu1,Student stu2) { //更改從大到小還是從小到大的順序,只需反一下。 if(stu1.id < stu2.id) return true; return false; } int main() { Student stu[] = { {1103,24}, {1102,23}, {1104,22}, {1107,25}, {1105,21}}; pFun fun = CompareAge; int size = sizeof(stu)/sizeof(Student); sort(stu,size,fun); for(int i = 0; i < size; ++i){ printf("%d %d\n",stu[i].id,stu[i].age); } return 0; }

 

通過代碼,我們必須分辨出哪個是庫提供方,哪個是用戶:

sort(...)方法是庫開者提供的,只是因為模擬問題所以把它寫在一個文件中了,我們可以假想它存放在某個靜態庫lib里面,這樣就和它有了界限。

庫開發者提供方法sort(...)供我們調用,形參里面還包括一個函數指針,就是調用用戶自己寫的函數,也即回調函數。所以它提供了規則,也就是說這個回調函數的形參是什么,返回值又是什么,假如用戶對於這個回調函數的形參和返回值啥都不知道,隨意寫了一個函數放進去,sort方法能接受嗎?顯然是不行的。

那么用戶怎么知道回調函數的形參和返回值等信息呢?庫開發方會告知,或者在它的文檔里面會有說明,就像在windows API開發窗口程序時提供的WinProc() 函數一樣,里面的形參必須一模一樣。(這個地方會牽涉到接口)

什么是回?

根據上面的代碼,我們知道,庫開發方提供了一個方法,然后形參又帶有一個函數指針,等着用戶去寫然后拿來調用,並在其實現中調用了這個函數。站在庫開發方的立場,我們可以總結為一句話:庫開發方調用了用戶的函數(回調函數)。

現在,我們把視角移到回調函數的立場上來看,它被調用了。但同時它也有參數,且傳進來的參數是庫開發方提供的數據,這里我們又可以總結一句話:回調函數調用了庫開發方的數據

這就是“回”的意思,你調我我也調用你,雙方互相調用。

回調函數的重點是什么?

根據上文分析,發現回調函數其實也不是難於理解,我覺得重點在於一定要划分清楚誰是庫開發方(也可稱為提供方,調用者),誰是用戶,把職能划分清楚是最關鍵的。

2018-01-22 12:46:14

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM