帮助理解函数对象的工作?

时间:2011-01-31 05:34:30

标签: c++ functor function-object

我在Wikipedia

上找到了此代码
class compare_class {
  public:
  bool operator()(int A, int B) const {
    return A < B;
  }
};
...
// Declaration of C++ sorting function.
template <class ComparisonFunctor> 
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);
...
int main() {
    int items[] = {4, 3, 1, 2};
    compare_class functor;
    sort_ints(items, sizeof(items)/sizeof(items[0]), functor);
}

首先我想知道如果在sort_ints中提到了仿函数而没有任何括号,A和B参数如何传递给operator()(int A,int B)。

然后我想到A和B被传递给sort_ints函数内的函数对象。但那么,sort_ints的声明是否应该使用'ComparisonFunctor * * * c'而不是'ComparisonFunctor c',因为它接收函数的地址?

在sort_ints函数中,函数调用函数是否会像这样完成?

functor(*begin_items, *(begin_items+1));

4 个答案:

答案 0 :(得分:6)

要理解为什么sort_ints按值获取其参数,您必须记住,作为比较器传递给它的对象不一定是函数指针。例如,如果您使用compare_class函数对象进行比较,那么您传递给函数的是compare_class类型的具体对象。您没有传递compare_class::operator()的地址,因为operator()是成员函数,而不是自由函数。也就是说,以下代码:

compare_class myComparator;
myComparator(a, b);

转换为

compare_class myComparator;
myComparator.operator() (a, b);

因此,参数需要通过值而不是指针来接收比较器,因为它需要一个接收器对象,而不是指向成员函数的指针或指向接收器对象的指针。

答案 1 :(得分:3)

正如您所指出的那样,sort_ints的使用没有任何暗示其对比较函数的要求:

compare_class functor;
sort_ints(items, sizeof(items)/sizeof(items[0]), functor);

sort_ints本身也没有:

template <class ComparisonFunctor>
void sort_ints(int* begin_items, int num_items, ComparisonFunctor c);

在class_compare中,我们只能推断出观察它将使用的功能不提供其他功能:

class compare_class
{
  public:
     bool operator()(int A, int B) const { return A < B; }
};

编译器确实离开它,直到它尝试编译sort_ints的实现,使用它实例化的类型,然后才能确定这是否全部挂起。 sort_ints必须具有你提到的那种陈述:

c(*begin_items, *(begin_items+1));    // note: functor argument is "c"

所以,你的理解在所有方面都是正确的。但是,值得注意的是,所提出的名为Concepts的C ++ 0x特性旨在使sort_int的要求更加明确,而无需考虑其实现。不幸的是,C ++ 0x不得不放弃这个功能,因为没有足够的时间和经验来确保它是最佳的。希望C ++的未来版本将包含这样的功能。您可以在'网上找到很多关于概念的讨论,它们应该可以帮助您更好地理解整体问题。

这是一个重要的问题,因为当你只有一些拼图 - 比如你想要使用的sort_ints函数但没有示例ComparisonFunctor时,你必须研究sort_ints的实现,以了解如何创建该Functor(除非你是超级幸运的,有很好的,现有的文件)。您可能会意外地使您的代码过于依赖现有的实现,因此当sort_int的实现稍后更改时,您的代码会无法接受地破坏或减慢 - 即使它足够巧妙,不会破坏测试用例或其他用户的代码或期望。所提供的ComparisonFunctor中的一个小错误也可能会从sort_int的内容中产生一个非常复杂且令人困惑的编译器错误消息 - 这不是向用户提供抽象服务的好方法。让我们希望Concepts能在一天之内完成......!

答案 2 :(得分:2)

请注意,compare_class是一个类。所以它可以声明,以你使用其他类的方式作为函数参数传递。

其次,compare_class实施operator()。这允许您执行以下操作:

compare_class obj;
obj(1, 2);

现在,上面代码片段中的第二个语句看起来像一个函数调用!所以从某种意义上说,实现operator()的类的任何对象都可以像函数一样使用。

这是功能对象的重点。此外,它还有其他优于函数指针的优点,您可以在帖子中找到相同的链接。

修改

sort_ints()内,仿函数应该执行以下操作:

for (int i = 1; i < num_items; i++)
    if (c(begin_items[i-1], begin_items[i]))
    {
        // begin_items[i-1] is less than begin_items[i], do stuff
    }

答案 3 :(得分:1)

是的,这是正确的。函数调用运算符应用于对象的名称,而不是对象的方法。此外,您没有传递函数的地址,而是传递(复制)对象。仿函数对象没有数据成员,只有operator()。