Linux C 函数指针应用---回调函数
?(這里引用了知乎上一些知友的回答,感覺不錯,有助于理解,這里引用作為借鑒,如有冒犯,煩請告知)
??? 我們先來回顧一下函數指針,函數指針是專門用來存放函數地址的指針,函數地址是一個函數的入口地址,函數名代表了函數的入口地址。當一個函數指針指向了一個函數,就可以通過這個指針來調用該函數,可以將函數作為參數傳遞給函數指針。
??? 那函數指針在我們實際編程中會起到怎樣的作用呢?前一篇關于函數指針的文章中,我們已經提到線程創建、信號注冊中都用到了函數指針,下面我們將介紹函數指針的一個經典應用---回調函數。
??? 看一看百度百科如何定義的回調函數:
?? ?回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用于對該事件或條件進行響應。
???? 簡單的講,一般寫程序是你調用系統的API,如果把關系反過來,你寫一個函數,讓系統調用你的函數,那就是回調了,那個被系統調用的函數就是回調函數。
???? 說詳細點,我們知道,編程分為兩類:系統編程(system programming)和應用編程(application programming)。所謂系統編程,簡單來說,就是編寫庫;而應用編程就是利用寫好的各種庫來編寫具某種功用的程序,也就是應用。系統程序員會給自己寫的庫留下一些接口,即API(application programming interface,應用編程接口),以供應用程序員使用。所以在抽象層的圖示里,庫位于應用的底下。
???? 當程序跑起來時,一般情況下,應用程序(application program)會時常通過API調用庫里所預先備好的函數。但是有些庫函數(library function)卻要求應用先傳給它一個函數,好在合適的時候調用,以完成目標任務。這個被傳入的、后又被調用的函數就稱為回調函數(callback function)。
???? 我們可以這樣理解:有一家旅館提供叫醒服務,但是要求旅客自己決定叫醒的方法。可以是打客房電話,也可以是派服務員去敲門,睡得死怕耽誤事的,還可以要求往自己頭上澆盆水。這里,“叫醒”這個行為是旅館提供的,相當于庫函數,但是叫醒的方式是由旅客決定并告訴旅館的,也就是回調函數。而旅客告訴旅館怎么叫醒自己的動作,也就是把回調函數傳入庫函數的動作,稱為登記回調函數(to register a callback function)。如下圖所示:
這樣看是不是都暈了,沒事,我們再來一次總結:
回調函數通俗的解釋:
普通函數:你所寫的函數調用系統函數,你只管調用,不管實現。
回調函數:系統調用你所寫的函數,你只管實現,不管調用。
?
那回調函數到底是如何使用的呢?我們先來解決個小問題:
1、回調函數在什么場景有用?
我要在特定時候執行一個任務,至于是什么時候我自己都不知道。比如某一時間到了或者某一事件發生或者某一中斷觸發。
2、回調函數怎么起作用?
把我要執行的這個任務寫成一個函數,將這個函數和某一時間或者事件或者中斷建立關聯。當這個關聯完成的時候,這個函數華麗的從普通函數變身成為回調函數。
3、回調函數什么時候執行?
當該回調函數關心的那個時間或者事件或者中斷觸發的時候,回調函數將被執行。
一般是觸發這個時間、事件或中斷的程序主體(通常是個函數或者對象)觀察到有一個關注這個東東的回調函數的時候,這個主體負責調用這個回調函數。
4、回調函數有什么好處?
最大的好處是你的程序變成異步了。也就是你不必再調用這個函數的時候一直等待這個時間的到達、事件的發生或中斷的發生(萬一一直不發生,你的程序會怎么樣?)。再此期間你可以做做別的事情,或者四處逛逛。當回調函數被執行時,你的程序重新得到執行的機會,此時你可以繼續做必要的事情了。
??? 借鑒知友的一個例子:
你去食堂打飯,你喜歡吃小炒熱飯菜,所以你去了一個小炒窗口。
你跟老板說了要×××蓋飯,老板說:你是100號,喊到你的號你就來拿菜。
然后你在旁邊跟同學吹牛、或者看手機、或者干點你想干的任何事情。。。
然后你聽到老板喊100號并且把菜放到窗口,你走到窗口,拿到你的菜。
?
這里面有幾個函數:
老板的部分:
1、老板提供一個點餐的函數 boss.Order(string 菜名,double 錢)
2、老板有個做飯的函數,此函數耗時較長boss.Cook()
3、老板提供一個事件,當boss.cook()執行完時,該事件被觸發,boss.OnCookFinish;
你的部分:
1、你需要有一個函數去訂餐,也就是你的函數中需要執行類似于boss.Order("紅燒肉蓋澆飯",20),比如是me.Hungry()
2、你需要有一個函數作為回調函數去關注boss.OnCookFinish事件,這樣當老板做好飯,你就可以知道是不是你的好了。
由于老板的事件發生的時候中會喊編號并且吧菜放到窗口,所以你的回調函數需要能夠接受1個編號和1個菜作為參數。
比如me.AcceptFood(int currNumber,object food)
所以整個程序的流程其實是這樣的:
[cpp]?view plaincopy 至此案例基本完成了一個完整的任務流程。
終于到我們的實例環節了!
回調函數實例一:
執行結果如下:
[cpp]?view plaincopy?
回調函數應用實例二:
[cpp]?view plaincopy執行結果如下:
[cpp]?view plaincopy?
希望對大家有幫助,謝謝!
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Linux C 函数指针应用---回调函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MathType插入带序号公式的两种方法
- 下一篇: matlab卷积不从0开始,matlab