函数对象 functor(整理)

函数对象 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---

你可能感兴趣的:(函数对象 functor(整理))