仿函數


仿函數的通俗定義:仿函數(functor)又稱為函數對象(function object)是一個能行使函數功能的類。

仿函數的語法幾乎和我們普通的函數調用一樣,不過作為仿函數的類,都必須重載operator()運算符

 class Func
{
     public:
         void operator() (const string& str) const 
        {
             cout<<str<<endl;
         }
 };  
1 Func myFunc;
2 myFunc("helloworld!");
>>>helloworld!

 

 

 

 函數(functor)又稱之為函數對象(function object),其實就是重載了operator()操作符的struct或class,沒有什么特別的地方。仿函數(functor)使一個類的使用看上去象一個函數,這個類就有了類似函數的行為,就是一個仿函數類了。

        如下面的代碼定義了一個二元的仿函數(有兩個參數):

 

struct IntLess
{
	bool operator()(int _left, int _right) const
	{
		return _left<_right;
	}
};

        為什么要使用仿函數呢 ?
        1)仿函數比一般的函數靈活。        

        2)仿函數有類型識別,可以作為模板參數。

        3)執行速度上仿函數比函數和指針要更快的。

        怎么使用仿函數?

        除了在stl里,別的地方你很少會看到仿函數的身影。而在stl里仿函數最常用的就是作為函數的參數,或者模板的參數。在stl里有自己預定義的仿函數,比如所有的運算符,=,-,*,/,比如比較符號<、>、<=、>=等。stl中的'<'仿函數是less:

 

		// 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);
		}
	};

從上面的定義可以看出,less就是一個含有模板的結構圖,並在結構體內重載了operator()運算符。再看發現less是從binary_function<...>繼承而來的,binary_function的定義如下:

 

		// TEMPLATE STRUCT greater
template<class _Ty>
	struct greater
		: 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);
		}
	};

        其 實binary_function只是做一些類型聲明而已,別的什么也沒做,但是在stl里為什么要做這些呢?如果你要閱讀過stl的源碼,你就會發現, 這樣的用法很多,其實沒有別的目的,就是為了方便,安全,可復用性等。但是既然stl里面內定如此了,所以作為程序員你必須要遵循這個規則!否則就別想安 全的使用stl!

       下面看一個簡單的仿函數應用的例子:

 

// 仿函數(functor或function object)
class Person
{
public:
	Person();
	//~Person();
	Person(string _firstname, string _lastname)
	{
		this->FirstName = _firstname;
		this->LastName = _lastname;
	}
public:
	string FirstName;
	string LastName;
	// additional information
};

class PersonCriterion
{
public:
	bool operator()(const Person& p1, const Person& p2)
	{
		return p1.LastName < p2.LastName ||(!(p2.LastName<p1.LastName) && p1.FirstName<p2.FirstName);
	}
};

int main( int argc, char* argv[])
{
	set<Person, PersonCriterion> colls;
	colls.insert(Person("Tom","James"));
	colls.insert(Person("Mike","James"));
	colls.insert(Person("Jane","Bush"));
	colls.insert(Person("Bill","Gates"));

	std::set<Person, PersonCriterion>::iterator iter;
	for ( iter = colls.begin(); iter!=colls.end(); ++iter)
	{		
		Person p = (Person)(*iter);		

		cout<< p.FirstName<<"  "<<p.LastName<<endl;
	}		
	getchar();
	return 1;
}

       在上面的例子中,定義了一個Person類,包含2個成員變量FirstName和LastName,並定義了一個PersonCriterion類來對Person進行排序。PersonCriterion定義了一個operator()用於比較兩個人的姓,如果姓相等,再比較其名。這樣coll的構造函數就會自動產生PersonCriterion的一個實體,並將所有的元素按此進行排序。

        注意,在這里PersonCriterion是一個類,我們把它作為set的template參數,而一般的函數卻不能做到這一點,進一步凸顯了仿函數的優勢。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM