函数对象 functor
任何类型实现了运算符(); 此运算符称为调用运算符, 或者应用运算符; STL把函数对象主要使用在排序条件的容器和算法中;
两大优势 1)函数对象可以包含状态; 2)函数对象是种类型, 可以用作模板参数;
创建函数对象
需要创建一个类型, 并实现()操作符;
class Functor { public: int operator()(int a, int b) { return a < b; } }; int main() { Functor f; int ans = f(1, 3); }
>f(1,3)看起来像是调用了一个函数, 实际上是调用了Function类的()操作符; 在语法上相似;
函数对象和容器
STL中在<functional>头文件中包含了函数对象; 函数对象的一个用途是作为容器的排序依据; e.g. set容器声明:
template < class Key, class Traits=less<Key>, class Allocator=allocator<Key> > class set
>set的第二个模板参数是函数对象less, 如果第一个参数小于第二个参数则返回true; 有些容器进行排序时需要一个方法比较两个元素, 这时可以使用函数对象; 我们可以创建函数对象来定义自己的排序方式, 并且在模板参数列表中指定它;
函数对象和算法
另一个用途是为算法准备的; e.g. remove_if算法声明:
template<class ForwardIterator, class Predicate> ForwardIterator remove_if( ForwardIterator _First, ForwardIterator _Last, Predicate _Pred );
>remove_if的最后一个参数是函数对象, 返回一个boolean值; 返回值为true, 则元素从_First到_Last被移除; 你可以是用任何在<functional>定义的函数对象作为参数_Pred, 也可以自己创建;
<refer to> http://msdn.microsoft.com/zh-cn/library/vstudio/aa985932.aspx
---End---
函数对象
函数对象不是函数指针, 实际上是实现了operator(), 括号操作符的类;
Note 和函数指针的定义方式不同, 调用方式类似; 函数对象可以携带附加数据, 函数指针不行;
e.g.函数对象保存数据
class Less { public: Less(int num):n(num){} bool operator()(int value) { return value < n; } private: int n; }; //--- Less lessObj(10); const int SIZE = 5; int array[SIZE] = {50, 20, 9, 7, 60}; int* pi = find_if(array, array+SIZE-1, Less(50));//指向20
>让一个函数既能接受函数指针又能接受函数对象, 最简便的方案就是模板
template<typename FUNC> int count_n(int* array, int size, FUNC func) { int count = 0; for(int i = 0; i < size; ++i) if(func(array[i])) count ++; return count; } bool Less10(int value) { return value <10; } //---输出2 cout<<count_n(array, SIZE, Less(10))<<endl; cout<<count_n(array, SIZE, Less10)<<endl;
>函数对象还有一个函数指针无法匹敌的用法: 封装类成员函数指针;
把类实体指针给函数对象保存起来, 就可以使用类实体(instance)指针来调用对应类实体成员函数了;
template<typename O> class memfun { public: memfun(void(O::*f)(const char*), O* o): pFunc(f), pObj(o){} void operator()(const char* name) { (pObj->*pFunc)(name); } private: void(O::*pFunc)(const char*); O* pObj; }; class A { public: void doIt(const char* name) { cout << "Hello " << name << "!";} }; //--- A a; memfun<A> call(&A::doIt, &a); // 保存 a::doIt指针以便调用 call("World");
>函数对象虽然能保存成员函数指针和调用信息, 以便想函数指针一样调用, 但是一个函数对象的定义, 最多只能实现一个指定参数数目的成员函数指针;
e.g. 标准库的mem_fun是一个函数对象, 只能支持0个和1个参数的两种成员函数指针; int A::func()或void A::func(int); etc.
boost库提供了boost::function类, 默认支持10个参数, 最多50个参数;
<refer to>http://www.cnblogs.com/ly4cn/archive/2007/07/21/826885.html
---End---