C++11新特性之八——函数对象function
http://www.cnblogs.com/yyxt/p/3987717.html
詳細(xì)請(qǐng)看《C++ Primer plus》(第六版中文版)
http://www.cnblogs.com/lvpengms/archive/2011/02/21/1960078.html
備注:
函數(shù)對(duì)象:
盡管函數(shù)指針被廣泛用于實(shí)現(xiàn)函數(shù)回調(diào),但C++還提供了一個(gè)重要的實(shí)現(xiàn)回調(diào)函數(shù)的方法,那就是函數(shù)對(duì)象。函數(shù)對(duì)象(也稱(chēng)“函數(shù)符”)是重載了“()”操作符的普通類(lèi)對(duì)象。因此從語(yǔ)法上講,函數(shù)對(duì)象與普通的函數(shù)行為類(lèi)似。
用函數(shù)對(duì)象代替函數(shù)指針有幾個(gè)優(yōu)點(diǎn):
首先,因?yàn)閷?duì)象可以在內(nèi)部修改而不用改動(dòng)外部接口,因此設(shè)計(jì)更靈活,更富有彈性。函數(shù)對(duì)象也具備有存儲(chǔ)先前調(diào)用結(jié)果的數(shù)據(jù)成員。在使用普通函數(shù)時(shí)需要將先前調(diào)用的結(jié)果存儲(chǔ)在全程或者本地靜態(tài)變量中,但是全程或者本地靜態(tài)變量有某些我們不愿意看到的缺陷。
其次,在函數(shù)對(duì)象中編譯器能實(shí)現(xiàn)內(nèi)聯(lián)調(diào)用,從而更進(jìn)一步增強(qiáng)了性能。這在函數(shù)指針中幾乎是不可能實(shí)現(xiàn)的。
C++11還提供了limbda表達(dá)式來(lái)實(shí)現(xiàn)函數(shù)的靈活調(diào)用。詳見(jiàn)《C++ Primer Plus》第18章。
----------------------------------------------------------------------------------------------------------------------------------------------------------
【以下轉(zhuǎn)自】http://www.cnblogs.com/hujian/archive/2012/12/07/2807605.html
function是一組函數(shù)對(duì)象包裝類(lèi)的模板,實(shí)現(xiàn)了一個(gè)泛型的回調(diào)機(jī)制。function與函數(shù)指針比較相似,優(yōu)點(diǎn)在于它允許用戶(hù)在目標(biāo)的實(shí)現(xiàn)上擁有更大的彈性,即目標(biāo)既可以是普通函數(shù),也可以是函數(shù)對(duì)象和類(lèi)的成員函數(shù),而且可以給函數(shù)添加狀態(tài)。 聲明一個(gè)function時(shí),需要給出所包裝的函數(shù)對(duì)象的返回值類(lèi)型和各個(gè)參數(shù)的類(lèi)型。比如,聲明一個(gè)function,它返回一個(gè)bool類(lèi)型并接受一個(gè)int類(lèi)型和一個(gè)float類(lèi)型的參數(shù),可以像下面這樣: function<bool (int, float)> f;下面簡(jiǎn)要介紹一下function的比較重要的幾個(gè)接口。
function(); 缺省構(gòu)造函數(shù),創(chuàng)建一個(gè)空的函數(shù)對(duì)象。如果一個(gè)空的function被調(diào)用,將會(huì)拋出一個(gè)類(lèi)型為bad_function_call的異常。 template <typename F> function(F g);這個(gè)泛型的構(gòu)造函數(shù)接受一個(gè)兼容的函數(shù)對(duì)象,即這樣一個(gè)函數(shù)或函數(shù)對(duì)象,它的返回類(lèi)型與被構(gòu)造的function的返回類(lèi)型或者一樣,或者可以隱式轉(zhuǎn)換,并且它的參數(shù)也要與被構(gòu)造的function的參數(shù)類(lèi)型或者一樣,或者可以隱式轉(zhuǎn)換。注意,也可以使用另外一個(gè)function實(shí)例來(lái)進(jìn)行構(gòu)造。這樣做,并且function g為空,則被構(gòu)造的function也為空。使用空的函數(shù)指針和空的成員函數(shù)指針也會(huì)產(chǎn)生空的function。如果這樣做,并且function g為空,則被構(gòu)造的function也為空。使用空的函數(shù)指針和空的成員函數(shù)指針也會(huì)產(chǎn)生空的function。
template <typename F> function(reference_wrapper<F> g); 這個(gè)構(gòu)造函數(shù)與前一個(gè)類(lèi)似,但它接受的函數(shù)對(duì)象包裝在一個(gè)reference_wrapper中,用以避免通過(guò)值來(lái)傳遞而產(chǎn)生函數(shù)或函數(shù)對(duì)象的一份拷貝。這同樣要求函數(shù)對(duì)象兼容于function的簽名。 function& operator=(const function& g); 賦值操作符保存g中的函數(shù)或函數(shù)對(duì)象的一份拷貝;如果g為空,被賦值的函數(shù)也將為空。 template<typename F> function& operator=(F g); 這個(gè)泛型賦值操作符接受一個(gè)兼容的函數(shù)指針或函數(shù)對(duì)象。注意,也可以用另一個(gè) function 實(shí)例(帶有不同但兼容的簽名)來(lái)賦值。這同樣意味著,如果g是另一個(gè)function實(shí)例且為空,則賦值后的函數(shù)也為空。賦值一個(gè)空的函數(shù)指針或空的成員函數(shù)指針也會(huì)使function為空。 bool empty() const; 這個(gè)成員函數(shù)返回一個(gè)布爾值,表示該function是否含有一個(gè)函數(shù)或函數(shù)對(duì)象。如果有一個(gè)目標(biāo)函數(shù)或函數(shù)對(duì)象可被調(diào)用,它返回 false 。因?yàn)橐粋€(gè)function可以在一個(gè)布爾上下文中測(cè)試,或者與0進(jìn)行比較,因此這個(gè)成員函數(shù)可能會(huì)在未來(lái)版本的庫(kù)中被取消,你應(yīng)該避免使用它。 void clear(); 這個(gè)成員函數(shù)清除 function, 即它不再關(guān)聯(lián)到一個(gè)函數(shù)或函數(shù)對(duì)象。如果function已經(jīng)是空的,這個(gè)調(diào)用沒(méi)有影響。在調(diào)用后,function肯定為空。令一個(gè)function為空的首選方法是賦0給它;clear 可能在未來(lái)版本的庫(kù)中被取消。 result_type operator()(Arg1 a1, Arg2 a2, ..., ArgN aN) const; 調(diào)用操作符是調(diào)用function的方法。你不能調(diào)用一個(gè)空的 function ,那樣會(huì)拋出一個(gè)bad_function_call的異常。調(diào)用操作符的執(zhí)行會(huì)調(diào)用function中的函數(shù)或函數(shù)對(duì)象,并返回它的結(jié)果。 下面分別給出使用function來(lái)包裝普通函數(shù),函數(shù)對(duì)象和類(lèi)的成員函數(shù)的參考代碼。 1、普通函數(shù) 1 int Add(int x, int y) 2 3 { 4 return x+y; 5 } 6 function<int (int,int)> f = Add; 7 int z = f(2, 3);2、函數(shù)對(duì)象
1 class CStudent2 {3 public:4 void operator() (string strName, int nAge)5 {6 cout << strName << " : " << nAge << endl; 7 }8 };9 10 CStudent stu; 11 function<void (string, int)> f = stu; 12 f("Mike", 12);3、類(lèi)的成員函數(shù)
1 struct TAdd2 {3 int Add(int x,int y)4 {5 return x+y;6 }7 };8 9 function<int (TAdd *, int, int)> f = TAdd::Add; 10 TAdd tAdd; 11 f(&tAdd, 2, 3); // 如果前面的模板參數(shù)為傳值或引用,直接傳入tAdd即可接下來(lái)我們來(lái)看看使用function來(lái)保存函數(shù)對(duì)象狀態(tài)的情況。考慮下面的代碼:
1 class CAdd2 {3 public:4 CAdd():m_nSum(0) { NULL; }5 int operator()(int i) //重載 () 運(yùn)算符6 {7 m_nSum += i;8 return m_nSum;9 } 10 11 int Sum() const 12 { 13 return m_nSum; 14 } 15 16 private: 17 int m_nSum; 18 }; 19 20 int main() 21 { 22 CAdd add; 23 function<int (int)> f1 = add; 24 function<int (int)> f2 = add; 25 cout << f1(10) << "," << f2(10) << "," << add.Sum() << endl; 26 return 0; 27 } 可能和大家想象的結(jié)果不一樣,上面程序的輸出是:10,10,0。我們將同一個(gè)函數(shù)對(duì)象賦值給了兩個(gè)function,然后分別調(diào)用了這兩個(gè)function,但函數(shù)對(duì)象中m_nSum的狀態(tài)并沒(méi)有被保持,問(wèn)題出在哪兒呢?這是因?yàn)閒unction的缺省行為是拷貝一份傳遞給它的函數(shù)對(duì)象,于是f1和f2中保存的都是add對(duì)象的拷貝,調(diào)用f1和f2后,add對(duì)象中的值并沒(méi)有被修改。C++ 11中提供了ref和cref函數(shù),來(lái)提供對(duì)象的引用和常引用的包裝。要使function能夠正確地保存函數(shù)對(duì)象的狀態(tài),我們可以這樣來(lái)修改代碼:
1 CAdd add; 2 function<int(int)> f1 = ref(add); 3 function<int(int)> f2 = ref(add); 另外,在兩個(gè)function之間賦值時(shí),如果源function保存的是函數(shù)對(duì)象的拷貝,則目標(biāo)function保存的也是函數(shù)對(duì)象的拷貝;如果源function保存的是函數(shù)對(duì)象的引用,則目標(biāo)function保存的也是函數(shù)對(duì)象的引用。總結(jié)
以上是生活随笔為你收集整理的C++11新特性之八——函数对象function的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 成都欢乐谷客服电话号码
- 下一篇: 从零开始学C++之STL(八):函数对象