Effective STL: 38 - 42 函數子、函數子類、函數及其他

這裏將的函數子(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;
};


41.理解ptr_fun、mem_fun、和mem_fun_ref的來由。


42.確保less<T>與operator<具有相同的語義。

應該儘量避免修改less 的行爲,因爲這樣做很可能誤導其他的程序員。如果希望以一種特殊的方式來排序對象,最好創建一個特殊的函數子類,它的名字不能是less,這樣做其實很簡單的。


發佈了63 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章