从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法
http://blog.csdn.net/jnu_simba/article/details/9500219
一、函數(shù)對象
1、函數(shù)對象(function object)也稱為仿函數(shù)(functor)
2、一個行為類似函數(shù)的對象,它可以沒有參數(shù),也可以帶有若干參數(shù)。
3、任何重載了調(diào)用運(yùn)算符operator()的類的對象都滿足函數(shù)對象的特征
4、函數(shù)對象可以把它稱之為smart function。
5、STL中也定義了一些標(biāo)準(zhǔn)的函數(shù)對象,如果以功能劃分,可以分為算術(shù)運(yùn)算、關(guān)系運(yùn)算、邏輯運(yùn)算三大類。為了調(diào)用這些標(biāo)準(zhǔn)函數(shù)對象,需要包含頭文件<functional>。
二、自定義函數(shù)對象
C++ Code?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include?<iostream> using?namespace?std; class?CFunObj { public: ????void?operator()() ????{ ????????cout?<<?"hello,function?object!"?<<?endl; ????} }; int?main() { ????CFunObj?fo; ????fo(); ????CFunObj()(); ????return?0; } |
注意:CFunObj()(); 表示先構(gòu)造一個匿名對象,再調(diào)用operator();
三、函數(shù)對象與容器
在這邊舉map 容器的例子,大家都知道m(xù)ap 在插入元素的時候會自動排序,默認(rèn)是根據(jù)key 從小到大排序,看map 的定義:
C++ Code?
| 1 2 3 4 5 6 7 8 9 10 | //?TEMPLATE?CLASS?map template?<?class?_Kty, ?????????class?_Ty, ?????????class?_Pr?=?less<_Kty>, ?????????class?_Alloc?=?allocator<pair<const?_Kty,?_Ty>?>?> class?map ????:?public?_Tree<_Tmap_traits<_Kty,?_Ty,?_Pr,?_Alloc,?false>?> { ????//?ordered?red-black?tree?of?{key,?mapped}?values,?unique?keys }; |
假設(shè)現(xiàn)在我們這樣使用 map< int, string > mapTest; 那么默認(rèn)的第三個參數(shù) _Pr = less<int>,再者,map 繼承的其中一個類
?_Tmap_traits 中有個成員:
?_Pr ?comp;// the comparator predicate for keys?
跟蹤進(jìn)insert 函數(shù),其中有這樣一句:
if (_DEBUG_LT_PRED(this->comp,?_Key(_Where._Mynode()), this->_Kfn(_Val)))
已知?#define _DEBUG_LT_PRED(pred, x, y) pred(x, y) 很明顯地,comp 在這里當(dāng)作函數(shù)對象使用,傳入兩個參數(shù),回頭看less 類的
模板實(shí)現(xiàn):
C++ Code?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | //?TEMPLATE?STRUCT?less template<class?_Ty> struct?less ????????:?public?binary_function<_Ty,?_Ty,?bool> { ????//?functor?for?operator< ????bool?operator()(const?_Ty?&_Left,?const?_Ty?&_Right)?const ????{ ????????//?apply?operator<?to?operands ????????return?(_Left?<?_Right); ????} }; |
即實(shí)現(xiàn)了operator() 函數(shù),左操作數(shù)小于右操作數(shù)時返回為真。
我們也可以在定義的時候傳遞第三個參數(shù),如map< int, string, greater<int> > mapTest; 則插入時按key 值從大到小排序(less,
?greater 都是STL內(nèi)置的類,里面實(shí)現(xiàn)了operator() 函數(shù)),甚至也可以自己實(shí)現(xiàn)一個類傳遞進(jìn)去,如下面例程所示:
C++ Code?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include?<map> #include?<string> #include?<iostream> using?namespace?std; struct?MyGreater { ????bool?operator()(int?left,?int?right) ????{ ????????return?left?>?right; ????} }; int?main(void) { ????map?<?int,?string,?/*greater<int>?*/MyGreater?>?mapTest; ????mapTest.insert(map<int,?string>::value_type(1,?"aaaa")); ????mapTest.insert(map<int,?string>::value_type(3,?"cccc")); ????mapTest.insert(map<int,?string>::value_type(2,?"bbbb")); ????for?(map?<?int,?string,?/*greater<int>?*/MyGreater?>::const_iterator?it?=?mapTest.begin();?it?!=?mapTest.end();?++it) ????{ ????????cout?<<?it->first?<<?"?"?<<?it->second?<<?endl; ????} ????return?0; } |
輸出為:
3 cccc
2 bbbb
1 aaaa
MyGreater 類并不是以模板實(shí)現(xiàn),只是比較key 值為int 類型的大小。
四、函數(shù)對象與算法
在STL一些算法中可以傳入函數(shù)指針,實(shí)現(xiàn)自定義比較邏輯或者計算,同樣地這些函數(shù)也可以使用函數(shù)對象來代替,直接看例程再稍
作分析:
C++ Code?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | #include?<vector> #include?<string> #include?<iostream> #include?<algorithm> using?namespace?std; void?PrintFun(int?n) { ????cout?<<?n?<<?'?'; } void?Add3(int?&n) { ????n?+=?3; } class?PrintObj { public: ????void?operator()(int?n) ????{ ????????cout?<<?n?<<?'?'; ????} }; class?AddObj { public: ????AddObj(int?number)?:?number_(number) ????{ ????} ????void?operator()(int?&n) ????{ ????????n?+=?number_; ????} private: ????int?number_; }; class?GreaterObj { public: ????GreaterObj(int?number)?:?number_(number) ????{ ????} ????bool?operator()(int?n) ????{ ????????return?n?>?number_; ????} private: ????int?number_; }; int?main(void) { ????int?a[]?=?{1,?2,?3,?4,?5}; ????vector<int>?v(a,?a?+?5); ????/*for_each(v.begin(),?v.end(),?PrintFun); ????cout<<endl;*/ ????for_each(v.begin(),?v.end(),?PrintObj()); ????cout?<<?endl; ????/*for_each(v.begin(),?v.end(),?Add3); ????for_each(v.begin(),?v.end(),?PrintFun); ????cout<<endl;*/ ????for_each(v.begin(),?v.end(),?AddObj(5)); ????for_each(v.begin(),?v.end(),?PrintFun); ????cout?<<?endl; ????cout?<<?count_if(a,?a?+?5,?GreaterObj(3))?<<?endl;?//計算大于3的元素個數(shù) ????return?0; } |
輸出為:
1 2 3 4 5
6 7 8 9 10
2
回顧for_each 的源碼,其中有這樣一句:?_Func(*_ChkFirst); 也就是將遍歷得到的元素當(dāng)作參數(shù)傳入函數(shù)。
上面程序使用了函數(shù)對象,實(shí)際上可以這樣理解?PrintObj()(*_ChkFirst); 即?PrintObj() 是一個匿名的函數(shù)對象,傳入?yún)?/span>
數(shù),調(diào)用了operator() 函數(shù)進(jìn)行打印輸出。使用函數(shù)對象的好處是比較靈活,比如直接使用函數(shù)Add3,那么只能將元素加3,而
使用函數(shù)對象Addobj(x), 想讓元素加上多少就傳遞給Addobj類,構(gòu)造一個對象即可,因?yàn)樗梢员4嬉环N狀態(tài)(類成員)。
count_if 中的 GreaterObj(3) 就類似了,將遍歷的元素當(dāng)作參數(shù)傳遞給operator(), 即若元素比3大則返回為真。
五、STL內(nèi)置的函數(shù)對象類
參考:
C++ primer 第四版
Effective C++ 3rd
C++編程規(guī)范
總結(jié)
以上是生活随笔為你收集整理的从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++11新特性之八——函数对象func
- 下一篇: 妇科输卵管不通咋办