函数对象的定义
C++标准中定义了两种形式的函数调用,ordinary function call 和member function call。 其中member function call是指对类的成员函数调用(静态函数属于ordinary function call)。
侯捷在stl源码解析中给出的函数对象定义如下:是一个行为上类似函数的对象,为了能够行为类似函数,其类别定义中必须自定义函数调用运算符(). 这个定义中所说的行为上类似函数,是指类似第一中函数调用的行为。比如如下的类F,就可以通过F()(1, 2)来进行函数调用。
struct F { int operator()(int a, int b) { return a - b; } };msdn中给出了另外一种 函数对象的的定义(http://msdn.microsoft.com/en-us/library/aa985932.aspx), 列出定义如下:
A function object, or functor, is any type that implements operator(). This operator is referred to as thecall operator or sometimes the application operator. The Standard Template Library uses function objects primarily as sorting criteria for containers and in algorithms.
Function objects provide two main advantages over a straight function call. The first is that a function object can contain state. The second is that a function object is a type and therefore can be used as a template parameter.
这个定义直接从实现上给出了函数对象就是自定义了运算符()的类型。函数对象的两个优点:一个是函数对象能够保存状态,另一个是函数对象时一个类型,因此可以在模板参数中使用。
基础实现
还是以上一篇文章C++函数指针中的代码为例,我定义一个可以接受函数对象的模板函数:
template<typename TFunc> int process(int a, int b, TFunc pFunc) { return pFunc(a, b); }该函数可以完成上文中的 algo的函数功能,可以用如下的语句调用process,可以达到和algo同样的效果:
int a = algo(1, 2, numAdd); a = process(1, 2, numMinus);此外,还可以用函数对象作为参数进行调用:
class processCls { public: int operator()(int a, int b) { return a % b; } }; a = process(5, 3, processCls());这样的process函数的适用性要比algo的范围广很多,不但能够接受函数指针,还能接受函数对象。结合stl中的各种算法,可以实现一些比较复杂一点的逻辑。
应用
stl的代码中,这个采用函数对象的算法很多,比如find_if,remove_if等等。
stl中的ptr_fun, mem_fun等都是用来在函数和函数对象之间进行配接的辅助类。ptr_fun用来将一个ordinary function call的函数封装成一个函数对象,将一个参数的ptr_fun源代码摘抄如下:
// TEMPLATE FUNCTION ptr_fun template<class _Arg, class _Result> inline pointer_to_unary_function<_Arg, _Result, _Result (__cdecl *)(_Arg)> ptr_fun(_Result (__cdecl *_Left)(_Arg)) { // return pointer_to_unary_function functor adapter return (std::pointer_to_unary_function<_Arg, _Result, _Result (__cdecl *)(_Arg)>(_Left)); }
template<class _Arg, class _Result, class _Fn = _Result (*)(_Arg)> class pointer_to_unary_function : public unary_function<_Arg, _Result> { // functor adapter (*pfunc)(left) public: explicit pointer_to_unary_function(_Fn _Left) : _Pfun(_Left) { // construct from pointer } _Result operator()(_Arg _Left) const { // call function with operand return (_Pfun(_Left)); } protected: _Fn _Pfun; // the function pointer };
从上面的代码可以看出ptr_fun最终返回的是一个pointer_to_unary_function对象,而对象中定义了 operator() 函数. mem_fun用来将一个成员函数转换成一个函数对象。这两个函数结合bind1st和bind2nd等可以做很多的函数配接。
wiki中的解释地址如下
http://en.wikipedia.org/wiki/Function_object
一个介绍后缀表达式的文章,很不错, 介绍怎么生成一个postfix-expression
http://www.cs.nthu.edu.tw/~wkhon/ds/ds10/tutorial/tutorial2.pdf