這裏將的函數子(functor),其實就是前面講過的仿函數。
38.遵循按值傳遞的原則來設計函數子類。
39.確保判別式是“純函數”。
純函數保證在不同的時刻調用相同的參數會得到相同的結果。純函數自己是沒有狀態的。
在仿函數類中,將operator()的函數聲明爲const。前面那個for_each的仿函數的求平均值的寫法是特例!!for_each()可以擁有自己的狀態!
40.若一個類是函數子,則應該使它配接。
如果有一個包含Widget對象的list容器,另外有一個函數可以用來判斷某個Widget指針所指的對象是否足夠“有趣”:
list<Widget*> widgetPtrs;
bool isInteresting(const Widget *pw);
如果需要找到該list第一個滿足isInteresting()條件的Widget指針,這很簡單:
list<Widget*>::iterator it = find_if(widgetPtrs.begin(),widgetPtrs.end(),isInteresting);
if(it != widgetPtrs.end());
但是如果要找到第一個不滿足足isInteresting()條件的Widget指針,這這種方法通不過編譯:
list<Widget*>::iterator it = find_if(widgetPtrs.begin(),widgetPtrs.end(),not1(isInteresting));
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
class AAA:public unary_function<int,bool> //特別注意這裏!!!
{
public:
bool operator()(int x) const
{
return x == 3;
}
};
int main()
{
vector<int> ivec;
for (int i = 0; i <= 5; ++i)
ivec.push_back(i);
vector<int>::iterator it = find_if(ivec.begin(), ivec.end(),not1(AAA()));
cout << *it << endl; //輸出0
return 0;
}
注意:C++新標準有find_if_not函數,可以完美的解決上面的問題。
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
class AAA
{
public:
bool operator()(int x) const
{
return x == 3;
}
};
int main()
{
vector<int> ivec;
for (int i = 0; i <= 5; ++i)
ivec.push_back(i);
vector<int>::iterator it = find_if_not(ivec.begin(), ivec.end(),AAA());
cout << *it << endl; //輸出0
return 0;
}
書上的意思是必須定義仿函數爲可配接的。如果仿函數的operator()只有一個實參,則它應該從unary_function繼承,而且必須指定operator()所帶的參數類型和返回值類型。如果仿函數的operator()有兩個實參,那麼它應該從binary_function繼承,而且必須指定三個類型,operator()的第一個和第二個參數的類型已經operator()的返回類型。
此外,傳遞給unary_function或binary_function的非指針類型需要去掉const和引用部分。然而如果以指針作爲參數或者返回類型的仿函數,則傳遞給unary_function或binary_function的類型和返回類型完全相同。(這裏特別注意)
如:
struct AAA:public binary_function<Widget,Widget,bool>
{
bool operator()(const Widget &lhs, const Widget &rhs) const;
};
struct BBB:public binary_function<const Widget*,const Widget*,bool>
{
bool operator()(const Widget *lhs, const Widget *rhs) const;
};
42.確保less<T>與operator<具有相同的語義。
應該儘量避免修改less 的行爲,因爲這樣做很可能誤導其他的程序員。如果希望以一種特殊的方式來排序對象,最好創建一個特殊的函數子類,它的名字不能是less,這樣做其實很簡單的。