2010-10-08 40 views
4

目前我正在学习标准模板库(STL)。这个程序为什么重载()运算符?

在这个程序中,我将一些长的值存储在关联容器中,然后根据单元的位置(根据单元位置的数字)对它们进行排序。

代码:

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

但我不明白,为什么我们的教授重载()运算符?

谢谢。

+1

仿佛重载'()'操作被称为在例如在所有它不会出现。也许它会在后面的练习中介绍? – 2010-10-08 08:32:46

+2

是它被称为时'的std :: set'试图插入按排序顺序(二进制谓词) – Benoit 2010-10-08 08:35:03

+0

@格雷格Hewgill运算符()元件被称为内部时,它执行store.insert(一些长值); – Searock 2010-10-08 08:35:34

回答

7

类的目的是实现排序以一定的方式在集合中的元素的功能。这被称为谓词。

它被实现为一个仿函数,即允许函数操作符用于一个对象(这是std :: set在引擎盖下)。这样做是STL和类似代码调用自定义对象的常用方式。 (函数指针比

所以它的使用这样的功能对象(又名仿函数)更多的限制:

Unitless functor; 

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

的std ::集是一个排序二叉树,所以它调用无单位的() - 运营商在每次插入几次,以确定每个长值应该去。

尝试编译并把一些的printf /性病::法院在那里,看看会发生什么。

而且,请注意回调像这样(即当你看不到你的代码的调用)在你的学习曲线开始时会令人感到恐惧和困惑。

  • 然后,你习惯了它,并全部使用它们,因为它们整齐。
  • 然后你的代码再次变得可怕又令人困惑,并且避免它们像瘟疫一样。
  • 然后,你成为一个管道磁带程序员,只在适当的地方使用它们,但从来没有在别处使用它们。

;)

+0

+1非常感谢。 – Searock 2010-10-08 08:59:13

7

UnitLess是一个binary 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); 
+0

对不起,我初学者,我不明白你想说什么:( – Searock 2010-10-08 08:33:59

+1

@ Space_C0wb0y运算符(),当它执行store.insert(一些长期值)被内部调用; – Searock 2010-10-08 08:36:47

+0

为什么你需要提供一个谓词对象?IIRC,'的std ::设置'将使用默认构造谓词(即'强的松()')。在这里,'UnitLess'是默认施工的。此外,如果你没有提供谓词_object_,你会'的std ::设置'不这样做,这显然不能用'的std ::少()' – MSalters 2010-10-08 08:42:22

2

他已经实施了用于标准自定义比较::设置,只有比较单位,即量模10.因为的std ::集是一个模板,它只是试图调用的东西看起来像一个函数,不管它是否是一个函数。通过重载operator(),你可以使它像一个函数一样工作。

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

在实际的例子编码有可能是一个略有瑕疵的演习是简单地通过单位对它们进行排序,但它很可能消除具有相同的单位,但实际上并没有重复号码。在你的示例代码中没有这样的例子(你有一个重复的,但这是整个值的重复)。如果除了4548之外还有3478个,Set比较器会认为它们是相同的,并且不允许重复。

顺便说一句,我不知道集是什么,我会叫“联想”的容器,它指的是键 - 值对。在设置中没有关联的值,只是键。

还有一点:运营商()应该是常数。

+0

你确定它不是'Associative Container'吗? http://www.sgi.com/tech/stl/set.html表示它是'Sorted Associative Container'。 – Searock 2010-10-08 10:04:50

+0

sgi.com的文档编辑认为它是一个关联容器,但似乎并不匹配,在维基百科即http://en.wikipedia.org/wiki/Associative_array描述,在这里似乎应该有与该键关联的一些值。你可以说一把钥匙把价值映射到自己身上。当然,std :: set的实现者和任何其他语言的等价物可能希望使用它们用于map的相同实现,即树。 – CashCow 2010-10-11 08:17:19