【转】回调函数,函数指针与函数对象
?原文出處:http://shudingbo.spaces.live.com/blog/cns!C33400475B08F157!423.entry?wa=wsignin1.0&sa=246515118
1.? 什么是回調函數
??? 回調函數(callback Function),顧名思義,用于回調的函數。? 回調函數只是一個功能片段,由用戶按照回調函數調用約定來實現的一個函數。回調函數是一個工作流的一部分,由工作流來決定函數的調用(回調)時機。回調函數包含下面幾個特性:
- ??? 屬于工作流的一個部分;
- ??? 必須按照工作流指定的調用約定來申明(定義);
- ??? 他的調用時機由工作流決定,回調函數的實現者不能直接調用回調函數來實現工作流的功能;
???
2. 回調機制
??? 回調機制是一種常見的設計模型,他把工作流內的某個功能,按照約定的接口暴露給外部使用者,為外部使用者提供數據,或要求外部使用者提供數據。
???? 如上圖所示,工作流提供了兩個對外接口(獲取參數、顯示結果),以回調函數的形式實現。
- ?“獲取參數”回調函數,需要工作流使用者設定工作流計算需要的參數。
- ?“顯示結果”回調函數,提供計算結果給工作流使用者。
2.? 回調機制應用
?? 使用回調機制,可以為工作流實現擴展。 可以把工作流中需要用戶干預的,或需要提供給用戶的數據以回調的模式提供給用戶。而用戶不需要知道整個工作的流程,只需知道回調函數的說明就可以使用工作流模塊提供的功能,這對信息的隱藏也是有作用的。
3. 回調機制的實現形式
- ??? 回調函數
- ??? 虛擬函數
- ??? 事件
?
/
?
以下轉自:http://www.cnblogs.com/heyutao/archive/2009/05/21/1486647.html
對于回調函數的編寫始終是寫特殊處理功能程序時用到的技巧之一。先介紹一下回調的使用基本方法與原理。
在這里設:回調函數為A()(這是最簡單的情況,不帶參數,但我們應用的實際情況常常很會復雜),使用回調函數的操作函數為B(), 但B函數是需要參數的,這個參數就是指向函數A的地址變量,這個變量一般就是函數指針。使用方法為:
int A(char *p); // 回調函數
typedef int(*CallBack)(char *p) ; // 聲明CallBack 類型的函數指針
CallBack myCallBack ; // 聲明函數指針變量
myCallBack = A; // 得到了函數A的地址 ?
B函數一般會寫為 B(CallBack lpCall,char * P,........); // 此處省略了p后的參數形式 。
所以回調機制可解為,函數B要完成一定功能,但他自己是無法實現全部功能的。 需要借助于函數A來完成,也就是回調函數。B的實現為:
B(CallBack lpCall,char *pProvide)
{
........... // B 的自己實現功能語句
lpCall(PpProvide); // 借助回調完成的功能 ,也就是A函數來處理的。
........... // B 的自己實現功能語句
}
(1)基于函數指針的回調函數:
#include < iostream >using ? namespace ?std;
typedef? int ?( * CallBack)( char * );//定義函數指針,該指針指向參數為 char *返回 int的函數
int ?A( char * ?str)
{
????cout << " function?A?starts " << endl;
????cout << str << endl;
????cout << " function?A?ends " << endl;
???? return ? 0 ;
}
void ?B(CallBack?call, char * ?str)
{
????cout << " function?B?starts " << endl;
????call(str);
????cout << " function?B?ends " << endl;
}
int ?main()
{
???? char * ?str = " hello,world! " ;
????B(A,str);
???? return ? 0 ;
}
結果:
function?B?starts
function?A?starts
hello,world!
function?A?ends
function?B?ends
(2)回調函數還有另外一種方式:函數對象。
函數對象(也稱“算符”)是重載了“()”操作符的普通類對象。因此從語法上講,函數對象與普通的函數行為類似。
用函數對象代替函數指針有幾個優點:
首先,因為對象可以在內部修改而不用改動外部接口,因此設計更靈活,更富有彈性。函數對象也具備有存儲先前調用結果的數據成員。在使用普通函數時需要將先前調用的結果存儲在全程或者本地靜態變量中,但是全程或者本地靜態變量有某些我們不愿意看到的缺陷。
其次,在函數對象中編譯器能實現內聯調用,從而更進一步增強了性能。這在函數指針中幾乎是不可能實現的。
下面的例子說明使用函數指針和函數對象實現整數求負數的的方法。
#include < iostream >using ? namespace ?std;
// 使用函數對象
class ?CallBack
{
public :
???? int ? operator ()( int );
};
int ?CallBack:: operator ()( int ?arg) //第一個圓括弧總是空的,因為它代表重載的操作符名;第二個圓括弧是參數列表。
{
???? return ?( - arg);
}
int ?fun(CallBack?call, int ?arg) //注意call是對象,而不是函數。
{
???? return ?call(arg); //編譯器將語句call(arg)轉化為call.operator()(arg);
}
// 使用函數指針
typedef? int ?( * callback)( int );
int ?callfun( int ?arg)
{
???? return ?( - arg);
}
int ?fun2(callback?call, int ?arg)
{
???? return ?call(arg);
}
int ?main()
{
????cout << fun(CallBack(), 3 ) << endl;
????cout << fun2(callfun, 3 ) << endl;
}
結果:
-3
-3
從上面的例子中可以看出,函數對象數據類型被限制在int,而通用性是函數對象的優勢之一,如何創建具有通用性的函數對象呢?方法是使用模板,也就是將重載的操作符“()”定義為類成員模板,以便函數對象適用于任何數據類型:如double,_int64或char:
#include < iostream >using ? namespace ?std;
// 使用函數對象類模板
template < class ?T >
class ?CallBack2
{
public :
????T? operator ()(T);
};
template < class ?T >
T?CallBack2 < T > :: operator ()(T?arg)
{
???? return ?( - arg);
}
int ?main()
{
???? // 使用函數對象類模板
????cout << CallBack2 < int > ()( 3 ) << endl;
????cout << CallBack2 < double > ()( 3.333 ) << endl;????
}
結果:
-3
-3.333
標準庫中函數對象?
C++標準庫定義了幾個有用的函數對象,它們可以被放到STL算法中。例如,sort()算法以判斷對象(predicate object)作為其第三個參數。判斷對象是一個返回Boolean型結果的模板化的函數對象。
轉載于:https://www.cnblogs.com/tangxun/archive/2012/02/20/2360174.html
總結
以上是生活随笔為你收集整理的【转】回调函数,函数指针与函数对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 因为没人用,英特尔安腾 / IA64 平
- 下一篇: 电子产品的好处和坏处是什么(超频的好处和