Functor - 它们对其他未实现operator()的类有什么影响力

时间:2012-08-26 12:55:38

标签: c++ class function pointers functor

我试图了解仿函数的“力量”。

好的,所以他们是指向函数的指针,但他们能做些什么呢?其他没有实现operator()的类不能做?

例如:

#include <iostream>
#include <assert.h>
#include <vector>
using namespace std;


class MultiplyBy
{
    private:
        int factor;

    public:
        MultiplyBy(int x) : factor(x) {}

        int operator () (int other) const
        {
            return factor * other;
        }
};


int main()
{

    MultiplyBy temp(5);
    int myResult = temp(5);  // now myResult holds 25
    cout << myResult << endl;
    return 0;
}

我们带他的另一个朋友

class MultiplyOther
{
    private:
        int factor;
    public:
        MultiplyOther(int x) : factor(x) {}
        int invokeMultiplyMe(int _other)
        {
            return _other * factor;
        }
};

做同样的事情:

int main()
{
    // MultiplyOther

    MultiplyOther notFunctor(4);
    int myOther = notFunctor.invokeMultiplyMe(3);
    cout << myOther << endl;
    return 0;
}

我们得到:

25
12

然后,算子的真正力量是什么?两个班级都保存州,或者我在这里遗漏了什么?

3 个答案:

答案 0 :(得分:4)

首先,它们具有可以使用的统一签名,例如通过算法只需要知道他们必须调用某些东西。

在您的示例中,MultiplyBy的实例可以被任何需要调用int并返回一个(或者可以构造为/ convertible到{{1的类型)的代码使用}})。使用第二个示例将要求代码了解int方法。

请注意,仿函数根本不是指向函数的指针。它们是可以使用函数调用的语法调用其实例的类。

答案 1 :(得分:1)

Functors对类没有任何特殊属性,但它们可以用作具有更高功能的函数。函数通常不能具有状态,如果它具有(通过使用静态变量),则所有函数调用之间共享状态。\

仿函数具有类的所有属性(特别是状态),但可以用作函数。一个很好的例子是用于STL算法的仿函数:

class Add
{
  public:
    Add(){sum = 0;};
    void operator()(int i)
    {
        sum += i;
    }
    int getSum(){return sum;};

    private:
    int sum;
}

int main()
{

std::vector<int> vint;
vint.push_back(2);
vint.push_back(3);
vint.push_back(4);
}

Add adder;

adder = std::for_each( vint.begin(); vint.end(), adder);

cout << adder.getSum();

答案 2 :(得分:0)

“所以它们是指向函数的指针” - 函数指针和仿函数完全不同。前者只是一个指向原始函数的普通指针。它没有任何状态。但是,仿函数或函数对象保持状态。 Functor是定义operator()的任何类。因此,可以通过函数的方式调用该类的任何对象。

C ++入门的代码片段......

template<class T>
class TooBig
{
    private:
    T cutoff;
    public:
    TooBig(const T & t) : cutoff(t) {}
    bool operator()(const T & v) { return v > cutoff; }
};

通过这个类,我们可以创建具有不同截止值的多个对象。 TooBig cutoff1(10); TooBig cutOff2(20);

使用仿函数的最佳位置之一是模板。例如,采取列表模板。它有一个remove_if函数,它删除列表中从参数返回true的所有值。

list list1; //让我们说它有一些价值 list list2; //让我们说它有一些值

现在,调用list1.remove_if(cutoff1); //应用list1的所有元素并删除大于cutOff1中存储的值的那些元素。 list2的相似之处。

THX!