引言:
可以為類類型的對象重載函數調用操作符:一般為表示操作的類重載調用操作符!
通過為類類型的對象提供一個實參表而使用調用操作符,所用的方式看起來系那個一個函數調用:
盡管absobj是一個對象而不是函數,我們仍然可以“調用”該對象,效果是運作有absobj對象定義的重載調用操作符,該操作接受一個int值并傳回它的絕對值。
函數調用操作符必須聲明為成員函數,一個類可以定義函數調用操作符的多個版本,由形參的數目或類型加以差別。
定義了調用操作符的類,其對象常稱為函數對象,即它們是行為類似函數的對象!
一、将函數對象用于标準庫算法
函數對象經常用作通用算法的實參。回憶曾經的一段程式:
使用gt6作為傳給count_if算法的實參,以計算使gt6傳回true的單詞數目:
1、函數對象可以比函數更靈活
通過将gt6定義為帶函數調用成員的類,可以使得傳遞的string與我們想要的長度進行測試,這樣,可以使用同一段代碼對不同長度的字元串進行計數:
2、使用gt_cls函數對象
這個count_if調用傳遞一個gt_cls類型的臨時對象而不再是名為gt6的函數。用整型值6來初始化那個臨時對象,構造函數将這個值存儲在bound成員中。現在,count_if每次調用它的函數形參時,它都使用gt_cls的調用操作符,該調用操作符根據bound的值測試其string實參的長度。
使用函數對象,容易修改程式以根據其他值進行測試,隻需為傳給count_if的對象改變構造函數實參即可。
還可以用來計算長度在1到10個字元的單詞數:
如果使用函數替代函數對象來編寫這個程式,可能需要編寫10個(⊙﹏⊙b汗)不同的函數,每個函數測試一個不同的值!
二、标準庫定義的函數對象
标準庫定義了一組算術、關系與邏輯函數對象類。标準庫還定義了一組函數擴充卡,使我們能夠特化或者擴充标準庫所定義的以及自定義的函數對象類。這些标準庫函數對象類型是在functional頭檔案中定義的。
<col>
标準庫函數對象
類型
函數對象
所應用的操作符
算術函數對象類型
plus<type>
+
minus<type>
-
multiplies<type>
*
divides<type>
/
modulus<type>
%
關系函數對象類型
negate<type>
equal_to<type>
==
not_equal_to<type>
!=
greater<type>
>
greater_equal<type>
>=
less<type>
<
less_equal<type>
<=
邏輯函數對象類型
logical_and<type>
&&
logical_or<type>
||
logical_not<type>
!
1、每個類表示一個給定操作符
每個标準庫函數對象類表示一個操作符,即每個類都定義了應用命名操作的調用操作符。如plus是表示加法操作符的模闆類型,plus模闆中的調用操作符對一對操作數使用+運算!
有兩個一進制函數對象類:一進制減(negate<type>))和邏輯非(logical_not<type>))。其餘的标準庫函數對象都是表示二進制操作符的二進制函數對象類。為二進制操作符定義的調用操作符需要兩個給定類型的形參,而一進制函數對象類型定義了接受一個實參的調用操作符。
2、表示操作數類型的模闆類型
每個函數對象類都是一個類模闆,我們需要為該模闆提供一個類型:
應用:
3、在算法中使用标準庫函數對象
函數對象常用于覆寫算法使用的預設操作符。例如,sort預設使用operator<按升序對容器進行排序。為了按降序對容器進行排序,可以傳遞函數對象greater。該類将産生一個調用操作符,調用基礎對象的大于操作符。
第二個sort函數的第三個實參greater<string>是一個臨時對象,是一個将>操作符應用于兩個string操作數的函數對象。
三、函數對象的函數擴充卡
标準庫提供了一組函數擴充卡,用于特化和擴充一進制和二進制函數對象。函數擴充卡分為:
1、綁定器:是一種函數擴充卡,它通過将一個操作數綁定到給定值,而将二進制函數對象轉換為一進制函數對象。有:bind1str,bind2nd.
每個綁定器接受一個函數對象和一個值,bind1st将給定值綁定到二進制函數對象的第一個實參,bind2nd将給定值綁定到二進制函數對象的第二個實參。
該擴充卡傳回一個函數對象,該對象用10作右操作數應用<=操作符,調用計算輸入範圍中小于或等于10的元素的個數。
2、求反器:将謂詞函數的真值求反。有:not1和not2。
not1将一進制函數對象的真值求反,not2将二進制函數對象的真值求反。