亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 2759 | 回復: 0
打印 上一主題 下一主題

回調函數原理以及自定義回調函數 [復制鏈接]

論壇徽章:
0
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2010-02-23 09:55 |只看該作者 |倒序瀏覽
回調函數原理以及自定義回調函數
回調函數原理
聲明CALLBACK   
調用(calling)機制從匯編時代起已經大量使用:準備一段現成的代碼,調用者可以隨時跳轉至此段代碼的起始地址,執(zhí)行完后再返回跳轉時的后續(xù)地址。CPU為此準備了現成的調用指令,調用時可以壓棧保護現場,調用結束后從堆棧中彈出現場地址,以便自動返回。借堆棧保護現場,它使調用者和被調者可以互不相識,于是才有了后來的函數和構件.   
此調用機制并非完美;卣{函數就是一例。例如,寫一個快速排序函數供他人調用,其中必包含比較大小。麻煩來了:此時并不知要比較的是何類數據--整數、浮點數、字符串?于是只好為每類數據制作一個不同的排序函數。更通行的辦法是在函數參數中列一個回調函數地址,并通知調用者:君需自己準備一個比較函數,其中包含兩個指針類參數,函數要比較此二指針所指數據之大小,并由函數返回值說明比較結果。排序函數借此調用者提供的函數來比較大小,借指針傳遞參數,可以全然不管所比較的數據類型。被調用者回頭調用調用者的函數(夠咬嘴的),故稱其為回調(callback)。
Windows系統(tǒng)還包含著另一種更為廣泛的回調機制,即消息機制。消息本是Windows的基本控制手段,乍看與函數調用無關,其實是一種變相的函數調用。發(fā)送消息的目的是通知收方
運行一段預先準備好的代碼,相當于調用一個函數。消息所附帶的WParam和LParam相當于函數的參數,只不過比普通參數更通用一些。應用程序可以主動發(fā)送消息,更多情況下是坐等  Windows發(fā)送消息。一旦消息進入所屬消息隊列,便檢感興趣的那些,跳轉去執(zhí)行相應的消息處理代碼。操作系統(tǒng)本是為應用程序服務,由應用程序來調用。而應用程序一旦啟動,卻要反過來等待操作系統(tǒng)的調用。這分明也是一種回調,或者說是一種廣義回調。其實,應用程序之間也可以形成這種回調。假如進程B收到進程A發(fā)來的消息,啟動了一段代碼,其中又向進程A發(fā)送消息,這就形成了回調。這種回調比較隱蔽,弄不好會搞成遞歸調用,若缺少終止條件,將會循環(huán)不已,直至把程序搞垮。若是故意編寫成此遞歸調用,并設好終止條件,倒是很有意思。但這種程序結構太隱蔽,除非十分必要,還是不用為好。
利用消息也可以構成狹義回調。上面所舉排序函數一例,可以把回調函數地址換成窗口handle。如此,當需要比較數據大小時,不是去調用回調函數,而是借API函數SendMessage   向指定窗口發(fā)送消息。收到消息方負責比較數據大小,把比較結果通過消息本身的返回值傳給消息發(fā)送方。所實現的功能與回調函數并無不同。當然,此例中改為消息純屬畫蛇添腳,反倒把程序搞得很慢。但其他情況下并非總是如此,特別是需要異步調用時,發(fā)送消息是一種不錯的選擇。假如回調函數中包含文件處理之類的低速處理,調用方等不得,需要把同步調用改為異步調用,去啟動一個單獨的線程,然后馬上執(zhí)行后續(xù)代碼,其余的事讓線程慢慢去做。一個替代辦法是借   API函數PostMessage發(fā)送一個異步消息,然后立即執(zhí)行后續(xù)代碼。這要比自己搞個線程省事許多,而且更安全。
如今我們是活在一個object時代。只要與編程有關,無論何事都離不開object。但object并未消除回調,反而把它發(fā)揚光大,弄得到處都是,只不過大都以事件(event)的身份出現,鑲嵌在某個結構之中,顯得更正統(tǒng),更容易被人接受。應用程序要使用某個構件,總要先弄清構件的屬性、方法和事件,然后給構件屬性賦值,在適當的時候調用適當的構件方法,還要給事件編寫處理例程,以備構件代碼來調用。何謂事件?它不過是一個指向事件例程的地址,與回調函數地址沒什么區(qū)別。不過,此種回調方式比傳統(tǒng)回調函數要高明許多。首先,它把讓人不太舒服的回調函數變成一種自然而然的處理例程,使編程者頓覺氣順。再者,地址是一個危險的東西,用好了可使程序加速,用不好處處是陷阱,程序隨時都會崩潰,F代編程方式總是想法把地址隱藏起來(隱藏比較徹底的如VB和Java),其代價是降低了程序效率。事件例程使編程者無需直接操作地址,但并不會使程序減速。

自定義回調函數
回調函數是不能顯式調用的函數;通過將回調函數的地址傳給調用者從而實現調用。回調函數使用是必要的,在我們想通過一個統(tǒng)一接口實現不同的內容,這時用回掉函數非常合適。比如,我們?yōu)閹讉不同的設備分別寫了不同的顯示函數:void TVshow(); void ComputerShow(); void NoteBookShow()...等等。這是我們想用一個統(tǒng)一的顯示函數,我們這時就可以用回掉函數了。
    void show(void (*ptr)());
使用時根據所傳入的參數不同而調用不同的回調函數。
不同的編程語言可能有不同的語法,下面舉一個c語言中回調函數的例子,其中一個回調函數不帶參數,另一個回調函數帶參數。
例子1:

//Test.c

#include
#include

int Test1()
{
   int i;
   for (i=0; i
   {
     printf("The %d th charactor is: %c\n", i, (char)('a' + i%26));
    }
   return 0;
}
int Test2(int num)
{
   int i;
   for (i=0; i
   {
    printf("The %d th charactor is: %c\n", i, (char)('a' + i%26));
    }
   return 0;
}

void Caller1(void (*ptr)())//指向函數的指針作函數參數
{
   (*ptr)();
}
void Caller2(int n, int (*ptr)())//指向函數的指針作函數參數,這里第一個參數是為指向函數的指針服務的,
{ //不能寫成void Caller2(int (*ptr)(int n)),這樣的定義語法錯誤。
   (*ptr)(n);
   return;
}
int main()
{
   printf("************************\n");
   Caller1(Test1); //相當于調用Test2();
   printf("&&&&&&************************\n");
   Caller2(30, Test2); //相當于調用Test2(30);
   return 0;
}

以上通過將回調函數的地址傳給調用者從而實現調用,但是需要注意的是帶參回調函數的用法。要實現回調,必須首先定義函數指針。函數指針的定義這里稍微提一下。比如: int (*ptr)(); 這里ptr是一個函數指針,其中(*ptr)的括號不能省略,因為括號的優(yōu)先級高于星號,那樣就成了一個返回類型為整型的函數聲明了。
=================================
轉載地址:
注: 狐貍認為, 回調函數實現多態(tài)函數只是附帶功能之一, 最主要是提供了一種代碼動態(tài)嵌入的手段, 實現函數內部中斷的一種方式.
文章出處:http://www.diybl.com/course/3_program/c++/cppsl/2008108/149015.html
原文地址
http://blog.csdn.net/woyaowenzi/archive/2009/03/02/3950116.aspx


本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u3/111961/showart_2184754.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯網協會會員  聯系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP