为什么这个程序重载()运算符?

时间:2010-10-08 08:28:21

标签: c++ stl set

目前我正在学习标准模板库(STL)。

在这个程序中,我将一些长值存储在Associative Container中,然后根据单位的位置对它们进行排序(根据单位的数量)。

代码:

#include <iostream>
#include <set>
#include <functional>

using namespace std;

class UnitLess
{
public:
    bool operator()(long first, long second)
    {
        long fu = first % 10;
        long su = second % 10;

        return fu < su;
    }
};

typedef set<long, UnitLess> Ctnr;

int main(void)
{
    Ctnr store;

    store.insert(3124);
    store.insert(5236);
    store.insert(2347);
    store.insert(6415);
    store.insert(4548);
    store.insert(6415);

    for(Ctnr::iterator i = store.begin(); i != store.end(); ++i)
    {
        cout << *i << endl;
    }
}

但是我不明白为什么我们的教授有过载()操作符?

感谢。

3 个答案:

答案 0 :(得分:7)

UnitLessbinary predicate,需要在STL中使用两个参数进行调用。

通过重载UnitLess中该函数的函数调用操作符,可以像使用两个longs并返回bool的函数一样使用。

UnitLess f;
f(5, 10);

相当于

bool f(long first, long second)
{
    long fu = first % 10;
    long su = second % 10;

    return fu < su;
}
f(5, 10);

答案 1 :(得分:7)

该类的目的是实现一个以给定方式对集合中的元素进行排序的函数。这被称为谓词。

它是作为一个仿函数实现的,即允许在一个对象上使用函数运算符(这就是std :: set在引擎盖下做的事情)。这样做是STL和类似代码调用自定义对象的常用方法。 (函数指针比函数对象(a.k.a. functor)更受限制

所以它的用法如下:

Unitless functor;

functor(123, 124); // returns true or false

std :: set是一个已排序的二叉树,因此它会在每个插入上多次调用Unitless的() - 运算符,以确定每个long值的位置。

尝试编译并在其中放置一些printf / std :: cout,看看会发生什么。

另外,请注意这样的回调(即当您看不到对代码的调用时)在学习曲线的开头是可怕且令人困惑的。

  • 然后你习惯了它并且全部使用它们,因为它们很整洁。
  • 然后你的代码再次变得可怕和混乱,你就像瘟疫一样避开它们。
  • 然后你成为了一个管道录音机程序员,只在适当的地方使用它们,但从未在其他地方使用它们。

答案 2 :(得分:2)

他已经实现了一个用于std :: set的自定义比较,它只比较单位,即模数为10的数量。因为std :: set是一个模板,它只是试图调用看起来像函数的东西,无论是否它是一个与否。通过重载operator(),你可以使它像一个函数。

在某些情况下,这样做实际上非常强大,因为struct / class可以存储状态以及额外的参数。整个boost :: function / boost :: bind基于这样做(并且你不需要每次都创建一个类)。

在编码的实际示例中,可能存在轻微的缺陷,因为练习只是按单位对它们进行排序,但它可以很好地消除具有相同单位但实际上不重复的数字。在您的示例代码中没有这样的示例(您有重复但是它是整个值的副本)。如果除了4548之外还有3478,则Set比较器会认为它们是相同的,并且不允许复制。

顺便说一下,我不确定set是什么叫做“关联”容器,它指的是键值对。集合中没有关联的值,只有键。

还有一点:operator()应该是const。