Ⅰ 回調函數一般都什麼作用求解
1.回調函數是一個很有用,也很重要的概念。當發生某種事件時,系統或其他函數將會自動調用你定義的一段函數。
2.回調函數就相當於一個中斷處理函數,由系統在符合你設定的條件時自動調用。為此,你需要做三件事:1,聲明;2,定義;3,設置觸發條件,就是在你的函數中把你的回調函數名稱轉化為地址作為一個參數,以便於系統調用。
3.所謂回調函數就是按照一定的形式由你定義並編寫實現內容,當發生某種事件時,而由系統或其它函數來調用的函數。使用回調函數實際上就是在調用某個函數時,將自己編寫的一個函數的地址作為參數傳遞給那個函數。而那個函數在需要的時候,也就是某種事情發生的時候,利用傳遞的函數地址調用回調函數,這時你可以利用這個機會在回調函數中處理消息或完成一定的操作。回調函數只能是全局函數,或者是靜態函數,因為這個函數只是在這個類中使用,所以為了維護類的完整性,我們用類的靜態成員函數來做回調函數。
4.對於很多初學者來說,往往覺得回調函數很神秘,很想知道回調函數的工作原理。本文將要解釋什麼是回調函數、它們有什麼好處、為什麼要使用它們等等問題,在開始之前,假設你已經熟知了函數指針。
(1)什麼是回調函數?
簡而言之,回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用為調用它所指向的函數時,我們就說這是回調函數。
(2)為什麼要使用回調函數?
因為可以把調用者與被調用者分開。調用者不關心誰是被調用者,所有它需知道的,只是存在一個具有某種特定原型、某些限制條件(如返回值為int)的被調用函數。
如果想知道回調函數在實際中有什麼作用,先假設有這樣一種情況,我們要編寫一個庫,它提供了某些排序演算法的實現,如冒泡排序、快速排序、shell排序、shake排序等等,但為使庫更加通用,不想在函數中嵌入排序邏輯,而讓使用者來實現相應的邏輯;或者,想讓庫可用於多種數據類型(int、float、string),此時,該怎麼辦呢?可以使用函數指針,並進行回調。
回調可用於通知機制,例如,有時要在程序中設置一個計時器,每到一定時間,程序會得到相應的通知,但通知機制的實現者對我們的程序一無所知。而此時,就需有一個特定原型的函數指針,用這個指針來進行回調,來通知我們的程序事件已經發生。實際上,SetTimer()API使用了一個回調函數來通知計時器,而且,萬一沒有提供回調函數,它還會把一個消息發往程序的消息隊列。
另一個使用回調機制的API函數是EnumWindow(),它枚舉屏幕上所有的頂層窗口,為每個窗口調用一個程序提供的函數,並傳遞窗口的處理程序。如果被調用者返回一個值,就繼續進行迭代,否則,退出。EnumWindow()並不關心被調用者在何處,也不關心被調用者用它傳遞的處理程序做了什麼,它只關心返回值,因為基於返回值,它將繼續執行或退出。
不管怎麼說,回調函數是繼續自C語言的,因而,在C++中,應只在與C代碼建立介面,或與已有的回調介面打交道時,才使用回調函數。除了上述情況,在C++中應使用虛擬方法或函數符(functor),而不是回調函數。
Ⅱ 回調函數的用法請舉例
我理解的回調函數就是將一個回調函數(固定的輸入參數個數與類型)的指針交給操作系統版,
當滿足回調函數的權調用條件時操作系統會自動調用回調函數,並將參數傳入回調函數
我們一般的程序按自已的流程走,一般用不到回調,但要響應事件時就要用到回調函數
因為不能像在DOS中那輪詢事件是否發生,只能靠操作系統在發出事件時調用事件的處理函數
Ⅲ 回調函數的用法和好處
函數調用形式本身沒有好壞之分
任何函數代碼如果有錯誤都可能導致軟體出問題,甚至導致崩潰
c 里可以使用指針,函數指針
這就使程序可以更靈活
當 函數指針 做為函數的參數,傳遞給一個被調用函數,
被調用函數就可以通過這個指針調用外部的函數,這就形成了回調
windows程序中 WndProc 就是使用回調的典型形式
一般的程序中回調函數作用不是非常明顯,可以不使用這種形式
最主要的用途就是當函數不處在同一個文件當中,比如動態庫,要調用
其他程序中的函數就只有採用回調的形式
#include "stdio.h"
#include "conio.h"
int add(int a, int b);
int libfun(int (*pDis)(int a, int b));
int main(void)
{
int (*pfun)(int a, int b);
pfun = add;
libfun(pfun);
}
int add(int a, int b)
{
return a + b;
}
int libfun(int (*pDis)(int a, int b))
{
int a, b;
a = 1;
b = 2;
printf("%d", pDis(a, b));
}
現在這幾個函數是在同一個文件當中
假如
int libfun(int (*pDis)(int a, int b))
是一個庫中的函數,就只有使用回調了,通過函數指針參數將外部函數地址傳入
來實現調用
函數 add 的代碼作了修改,也不必改動庫的代碼,就可以正常實現調用
便於程序的維護和升級
Ⅳ cocos creator回調函數怎麼用
onLoad 回調會在這個組件所在的場景被載入 的時候觸發,在 onLoad 階段,保證了你可以獲取到場景中的其他節點,以及節點關聯的資源數據。
Ⅳ 各位大牛,我現在在JS方法中遇到回調函數的問題。請問一下回調函數是怎麼使用的,在什麼時候返回
父窗口可以在取得iframe對象以後(document.getElementById)以後(比如ifa),用ifa.function1()來調用iframe裡面window.function1函數,iframe裡面的js可以用parent.function2()來調用父窗口裡面的window.function2函數。
賦值的話就更簡單了,ifa.aaa = 0,就是把子窗口裡面的window.aaa賦值為0了,子窗口裡面的js直接用window.aaa就可以取得這個值,同理,iframe裡面的js用parent.bbb = 1,就是把父窗口的window.bbb賦值為1了,父窗口就可以用window.bbb來取用這個值了。
Ⅵ 如何理解回調函數的作用與實現
回調函數的主要作用:
1.回調函數就是本模塊實現的回調函數,但是調用卻不是自己來調,而是由別的模塊來調的
2.可更好的把握調用函數的時機,
回調函數依賴對應注冊回調的模塊,回調函數由該模塊觸發,觸發的條件、時間點,都是由該模塊控制
(通常由該模塊的事件消息,觸發)
3.在不同模塊間進行使用,可令觸發邏輯與業務邏輯分離,讓代碼功能性上更為清晰,易懂
注意點:
回調函數跑的事情,都是在觸發回調的線程下進行的,如果回調函數中干很多事,很容易造成觸發模塊-所屬線程堵塞
這對於多線程編程時,需特別注意,線程堵塞,會影響其他線程運行時序,造成一些bug
通常用法:
以庫的形式,供別人調用實現
以上是根據網上相應資料,再加上自己的總結體會,整理出來的
下面是自己寫的一個回調函數-用法的例子:
主要 分成2個模塊
A模塊為定義回調函數的模塊,負責觸發回調,一般為事件消息模塊
B模塊為實現回調函數的模塊,一般為處理業務邏輯模塊
A模塊需向B模塊暴露定義及注冊回調介面
typedef void (*TestCB)(char testData);
void A_SetTestCb(TestCB pTestCb)
B模塊實現具體的回調函數就可以了,本例中即B_UserTestCbDetail(char testData)
主要分3步:注冊回調函數->消息事件觸發回調函數->執行回調函數
附代碼:
#include "stdio.h"
//定義回調函數-別名,方便後續使用------需提供給模塊B
typedef void (*TestCB)(char testData);
//模塊A內部的全局回調變數,用於模塊A內部綁定注冊回調用
TestCB g_pTestCbHandle;
/*****************************************************
模塊A對外函數---------需提供給模塊B
模塊A內部定義的全局callback變數與外部模塊注冊的
回調函數綁定起來,用於後續模塊A,滿足觸發條件後,觸
發回調
******************************************************/
void A_SetTestCb(TestCB pTestCb)
{
g_pTestCbHandle = pTestCb;
}
/*****************************************************
模塊A內部函數
通常為A模塊因為某些條件符合了,觸發了對應的事件
從而調用對應的callback函數
******************************************************/
void A_CallTestCb()
{
char testData = 100;
//觸發調用回調實現函數
g_pTestCbHandle(testData);
}
/*****************************************************
模塊B內部函數
模塊B實現的回調函數-具體操作
******************************************************/
void B_UserTestCbDetail(char testData)
{
printf("step 3\n");
printf("[do] call-back\n");
//具體實現
printf("UserTestCbDetail, call back is achieve! testData = %d\n", testData);
}
void main()
{
printf("step 1\n");
printf("[register] call-back\n");
A_SetTestCb(B_UserTestCbDetail);
printf("step 2\n");
printf("[call] call-back\n");
A_CallTestCb();
}
Ⅶ 關於如何在類中使用回調函數,請高手給個解答。
一個是你可以不用 typedef 而直接在 struct 內部定義正確參數類型的函數指針;
要不你可以把第一行:
typedef void* CP_Streamp;
改成:
struct CPs_InStream;
typedef CPs_InStream *CP_Streamp;
還有你的那個 ???_Read 函數的最後一個參數與函數指針不符!
另外,團IDC網上有許多產品團購,便宜有口碑
Ⅷ ros中python回調函數是不是必須要有rospy,spin或者rospy,spinonce函數
在使用ros::spin()的情況下,一般來說在初始化時已經設置好所有消息的回調,並且不需要其他背景程序運行。這樣以來,每次消息到達時會執行用戶的回調函數進行操作,相當於程序是消息事件驅動的;而在使用ros::spinOnce()的情況下,一般來說僅僅使用回調不足以完成任務,還需要其他輔助程序的執行:比如定時任務、數據處理、用戶界面等。
關於消息接收回調機制在ROS官網上略有說明 (callbacks and spinning)。總體來說其原理是這樣的:除了用戶的主程序以外,ROS的socket連接控制進程會在後台接收訂閱的消息,所有接收到的消息並不是立即處理,而是等到spin()或者spinOnce()執行時才集中處理。所以為了保證消息可以正常接收,需要尤其注意spinOnce()函數的使用 (對於spin()來說則不涉及太多的人為因素)。
I. 對於速度較快的消息,需要注意合理控制消息隊列及spinOnce()的時間。例如,如果消息到達的頻率是100Hz,而spinOnce()的執行頻率是10Hz,那麼就要至少保證消息隊列中預留的大小大於10。
II. 如果對於用戶自己的周期性任務,最好和spinOnce()並列調用。即使該任務是周期性的對於數據進行處理,例如對接收到的IMU數據進行Kalman濾波,也不建議直接放在回調函數中:因為存在通信接收的不確定性,不能保證該回調執行在時間上的穩定性。
// 示例代碼
ros::Rate r(100);
while (ros::ok())
{
libusb_handle_events_timeout(...); // Handle USB events
ros::spinOnce(); // Handle ROS events
r.sleep();
}
III. 最後說明一下將ROS集成到其他程序架構時的情況。有些圖形處理程序會將main()包裹起來,此時就需要找到一個合理的位置調用ros::spinOnce()。比如對於OpenGL來說,其中有一個方法就是採用設置定時器定時調用的方法:
// 示例代碼
void timerCb(int value) {
ros::spinOnce();
}
glutTimerFunc(10, timerCb, 0);
glutMainLoop(); // Never returns
Ⅸ 回調函數是怎麼實現的為什麼系統就會去調用回調函數
回調函數是應用程序提供給Windows系統DLL或其它DLL調用的函數,一般用於截獲消息、獲取系統信息或處理非同步事件。應用程序把回調函數的地址指針告訴DLL,而DLL在適當的時候會調用該函數。回調函數必須遵守事先規定好的參數格式和傳遞方式,否則DLL一調用它就會引起程序或系統的崩潰。通常情況下,回調函數採用標准WindowsAPI的調用方式,即__stdcall,當然,DLL編制者可以自已定義調用方式,但客戶程序也必須遵守相同的規定。在__stdcall方式下,函數的參數按從右到左的順序壓入堆棧,除了明確指明是指針或引用外,參數都按值傳遞,函數返回之前自己負責把參數從堆棧中彈出。 程序在調用一個函數(function)時(通常指api).相當於程序(program)呼叫(Call)了一個函數(function)關系表示如下: call(調用) program --------------------→ dll 程序在調用一個函數時,將自己的函數的地址作為參數傳遞給程序調用的函數時(那麼這個自己的函數稱回調函數).需要回調函數的 DLL 函數往往是一些必須重復執行某些操作的函數.關系表示如下: call(調用) program --------------------→ dll ↑ ¦ ¦_______________________________¦ callback(回調) 當你調用的函數在傳遞返回值給回調函數時,你就可以利用回調函數來處理或完成一定的操作。至於如何定義自己的回調函數,跟具體使用的API函數有關,很多不同類別的回調函數有各種各樣的參數,有關這些參數的描述一般在幫助中有說明回調函數的參數和返回值等.其實簡單說回調函數就是你所寫的函數滿足一定條件後,被DLL調用! Windows 系統還包含著另一種更為廣泛的回調機制,即消息機制。消息本是 Windows 的基本控制手段,是一種變相的函數調用。發送消息的目的是通知收方運行一段預先准備好的代碼,相當於調用一個函數。消息所附帶的 WParam 和 LParam 相當於函數的參數,應用程序可以主動發送消息,更多情況下是坐等 Windows 發送消息。一旦消息進入所屬消息隊列,便檢感興趣的那些,跳轉去執行相應的消息處理代碼。操作系統本是為應用程序服務,由應用程序來調用。而應用程序一旦啟動,卻要反過來等待操作系統的調用。這分明也是一種回調,或者說是一種廣義回調。其實,應用程序之間也可以形成這種回調。假如進程 B 收到進程 A 發來的消息,啟動了一段代碼,其中又向進程 A 發送消息,這就形成了回調。這種回調比較隱蔽,弄不好會搞成遞歸調用,若缺少終止條件,將會循環不已,直至把程序搞垮。利用消息也可以構成狹義回調。把回調函數地址換成窗口 handle。如此,當需要比較數據大小時,不是去調用回調函數,而是借 API 函數 SendMessage 向指定窗口發送消息。收到消息方負責比較數據大小,把比較結果通過消息本身的返回值傳給消息發送方。所實現的功能與回調函數並無不同。當然,此例中改為消息純屬畫蛇添腳,反倒把程序搞得很慢。但其他情況下並非總是如此,特別是需要非同步調用時,發送消息是一種不錯的選擇。假如回調函數中包含文件處理之類的低速處理,調用方等不得,需要把同步調用改為非同步調用,去啟動一個單獨的線程,然後馬上執行後續代碼,其餘的事讓線程慢慢去做。一個替代辦法是借 API 函數 PostMessage 發送一個非同步消息,然後立即執行後續代碼。這要比自己搞個線程省事許多,而且更安全。 只要與編程有關,無論何事都離不開 object。但 object 並未消除回調,反而把它發揚光大,弄得到處都是,只不過大都以事件(event)的身份出現,鑲嵌在某個結構之中,顯得更正統,更容易被人接受。應用程序要使用某個構件,總要先弄清構件的屬性、方法和事件,然後給構件屬性賦值,在適當的時候調用適當的構件方法,還要給事件編寫處理常式,以備構件代碼來調用。何謂事件?它不過是一個指向事件常式的地址,與回調函數地址沒什麼區別。不過,此種回調方式比傳統回調函數要高明許多。首先,它把讓人不太舒服的回調函數變成一種自然而然的處理常式,使編程者頓覺氣順。再者,地址是一個危險的東西,用好了可使程序加速,用不好處處是陷阱,程序隨時都會崩潰。現代編程方式總是想法把地址隱藏起來(隱藏比較徹底的如 VB 和 Java),其代價是降低了程序效率。事件常式(?)使編程者無需直接操作地址,但並不會使程序減速。 回調用於層間協作,上層將本層函數安裝在下層,這個函數就是回調,而下層在一定條件下觸發回調,例如作為一個驅動,是一個底層,他在收到一個數據時,除了完成本層的處理工作外,還將進行回調,將這個數據交給上層應用層來做進一步處理,這在分層的數據通信中很普遍。其實回調和API非常接近,他們的共性都是跨層調用的函數。但區別是API是低層提供給高層的調用,一般這個函數對高層都是已知的;而回調正好相反,他是高層提供給底層的調用,對於低層他是未知的,必須由高層進行安裝,這個安裝函數其實就是一個低層提供的API,安裝後低層不知道這個回調的名字,但它通過一個函數指針來保存這個回調,在需要調用時,只需引用這個函數指針和相關的參數指針。 其實:回調就是該函數寫在高層,低層通過一個函數指針保存這個函數,在某個事件的觸發下,低層通過該函數指針調用高層那個函數。 軟體模塊之間總是存在著一定的介面,從調用方式上,可以把他們分為三類:同步調用、回調和非同步調用。同步調用是一種阻塞式調用,調用方要等待對方執行完畢才返回,它是一種單向調用;回調是一種雙向調用模式,也就是說,被調用方在介面被調用時也會調用對方的介面;非同步調用是一種類似消息或事件的機制,不過它的調用方向剛好相反,介面的服務在收到某種訊息或發生某種事件時,會主動通知客戶方(即調用客戶方的介面)。回調和非同步調用的關系非常緊密,通常我們使用回調來實現非同步消息的注冊,通過非同步調用來實現消息的通知。同步調用是三者當中最簡單的,而回調又常常是非同步調用的基礎。 對於不同類型的語言(如結構化語言和對象語言)、平台(Win32、JDK)或構架(CORBA、DCOM、WebService),客戶和服務的交互除了同步方式以外,都需要具備一定的非同步通知機制,讓服務方(或介面提供方)在某些情況下能夠主動通知客戶,而回調是實現非同步的一個最簡捷的途徑。 對於一般的結構化語言,可以通過回調函數來實現回調。回調函數也是一個函數或過程,不過它是一個由調用方自己實現,供被調用方使用的特殊函數。在面向對象的語言中,回調則是通過介面或抽象類來實現的,我們把實現這種介面的類成為回調類,回調類的對象成為回調對象。對於象C++或Object Pascal這些兼容了過程特性的對象語言,不僅提供了回調對象、回調方法等特性,也能兼容過程語言的回調函數機制。 Windows平台的消息機制也可以看作是回調的一種應用,我們通過系統提供的介面注冊消息處理函數(即回調函數),從而實現接收、處理消息的目的。由於Windows平台的API是用C語言來構建的,我們可以認為它也是回調函數的一個特例。 對於分布式組件代理體系CORBA,非同步處理有多種方式,如回調、事件服務、通知服務等。事件服務和通知服務是CORBA用來處理非同步消息的標准服務,他們主要負責消息的處理、派發、維護等工作。對一些簡單的非同步處理過程,我們可以通過回調機制來實現。
Ⅹ C++中的回調函數函數怎麼用
就是在執行beginthreadex的過程中會調用wrkFun函數,或者beginthreadex會記錄下wrkFun這個指針所指的地址,在適當的時候調用這個函數。