2

我在维基百科上找到了这段代码

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);
}

起初我想知道 A 和 B 参数是如何传递给 operator()(int A, int B) 的,当在 sort_ints 中提到函子时甚至没有任何括号。

然后我发现 A 和 B 被传递给 sort_ints 函数内的函数对象。但是,sort_ints 的声明不应该有 'ComparisonFunctor* * * c' 而不是 'ComparisonFunctor c',因为它正在接收函数的地址?

在 sort_ints 函数内部,对函子的函数调用会像这样吗?

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

4 回答 4

6

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

compare_class myComparator;
myComparator(a, b);

翻译成

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

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

于 2011-01-31T05:43:50.120 回答
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"

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

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

于 2011-01-31T05:59:41.443 回答
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
    }
于 2011-01-31T05:41:13.550 回答
1

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

于 2011-01-31T05:44:12.973 回答