比较函子类型与运算符<
Comparison Functor Types vs. operator<
在 Google C++ 风格指南中,关于运算符重载的部分建议不要重载任何运算符("除非在极少数特殊情况下"(。具体而言,它建议:
特别是,不要超载
operator==
或operator<
只是为了 您的类可以用作 STL容器;相反,您应该 创建相等和比较函子 声明容器时的类型。
我对这样的函子是什么样子有点模糊,但我的主要问题是,你为什么要为此编写自己的函子?定义operator<
,并使用标准的std::less<T>
函数,不是更简单吗?使用一个比另一个有什么优势吗?
除了更基本的类型外,小于操作并不总是微不足道的,甚至相等也可能因情况而异。
想象一下,一家航空公司想要为所有乘客分配一个登机号的情况。这个数字反映了登机顺序(当然(。现在,是什么决定了谁先于谁?您可以只采用客户注册的顺序 - 在这种情况下,小于操作将比较签到时间。您还可以考虑客户为门票支付的价格 - 低于现在比较票价的价格。
。等等。总而言之,在Passenger
类上定义operator <
是没有意义的,尽管可能需要将乘客放在分类的容器中。我认为这就是谷歌警告的。
一般来说,定义operator<
更好、更简单。
您希望使用函子的情况是,当您需要多种方法来比较特定类型时。例如:
class Person;
struct CompareByHeight {
bool operator()(const Person &a, const Person &b);
};
struct CompareByWeight {
bool operator()(const Person &a, const Person &b);
};
在这种情况下,可能没有一种好的"默认"方法来比较和排序人员,因此不定义operator<
和使用函子可能会更好。你也可以说,通常人是按身高排序的,所以operator<
只是叫CompareByHeight
,任何需要按体重排序的人都必须明确使用CompareByWeight
。
很多时候,问题在于定义函子由类的用户决定,因此每当需要在有序容器中使用类时,您往往会获得对同一事物的许多重新定义。
好吧,根据你引用的网页,函子没有太大的优势("[运算符]可以愚弄我们的直觉,认为昂贵的操作是廉价的内置操作。
我的意思是,人们应该努力使你尽可能多地对一流对象进行类,对我来说,这意味着让他们尽可能多地理解运算符。
自从我编写函子以来已经有一段时间了,但它看起来像这样:
class MyClass {....}
class LessThanMyClass : std:binary_function<MyClass, MyClass, bool>
{
public bool operator()(MyClass lhs, MyClass rhs)
{ return /* determine if lhs < rhs */ ; }
}
vector<MyClass> objs;
std::sort(objs.begin(), objs.end(), LessThanMyClass());
}
我认为不定义运算符<背后的信息是排序是集合的属性,而不是对象的属性。同一对象的不同集合可能具有不同的顺序。因此,在指定集合的类型而不是运算符时,应使用单独的函子><。>
但实际上,您的许多类可能具有自然排序,这是应用程序中集合中使用的唯一顺序。在其他情况下,排序甚至可能与应用程序无关,仅与集合相关,以便以后可以找到项目。在这些情况下,定义运算符<是完全有意义的。>
请记住,当我们设计对象模型时,我们只是对现实世界的一个子集进行建模。在现实世界中,可能有无数种不同的方法来对同一类的对象进行排名,但在我们工作的应用程序域中,可能有一种相关的方法。
如果代码演变为需要与第一个排序相同的第二个排序,则应重构该类以删除运算符<并将两个排名函数放在单独的函子中。这表明没有一个排名比其他排名更重要的意图。>
对于算术运算符,除非实现算术类型,否则不应重载这些运算符。
当然,每条规则都有例外。如果你不知道你是否应该破例,你可能不应该。经验将是您的向导。
我可能不会像谷歌风格指南那样走得那么远。
我认为他们的意思是,当您重载 operator<
和 operator==
时,您正在为该类型的每次使用做出决定,而函子类型仅适用于该集合。
如果您唯一需要比较器就是将项目放入集合中,那么最好有一个专门针对该上下文的函数,而不是适用于所有上下文的运算符。
您可能希望按时间顺序对采购订单进行排序,但通常,按总价比较它们是有意义的。 如果我们超载operator<
来比较日期,以便我们可以将它们加载到集合中,我们就会引入另一个客户可能会滥用我们operator<
的风险,他们可能认为我们的比较了总价。
函子是具有operator ()
的类。 在这种情况下,该方法将采用要比较的类型的两个参数,如果第一个参数小于第二个参数,则返回bool
结果。
编辑:为了建立在 James Curran 所说的基础上,你可以在类中定义你的函子。 因此,例如:
class MyClass
{
struct LessThan : public std::binary_function<MyClass, MyClass, bool>
{
bool operator()(const MyClass & first, const MyClass & second) const
{
return first.key < second.key;
}
};
};
具有讽刺意味的是,函子还需要覆盖运算符(函数调用运算符 - operator ()
(,所以我不确定他们的观点是什么。
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 如何显式调用运算符<<
- 为什么COUT在朋友函数中不起作用,该功能超载了操作员&lt;&lt;这是一个iStream运算符
- C++运算符<<调用::ostream而不是std::osttream
- BOOST ::变体无法解决运算符&lt;&lt;对于STD :: Ostream
- 过载输出<<用于类的运算符,以打印其中的元组
- C++ostream:没有运算符匹配<<&应在'&'代币
- 重载运算符<<:此运算符函数的参数太多
- C++继承运算符<<
- 重载运算符<<用于模板类.即使使用好友关键字也无法获得私人会员
- 如何过载<<用于YAML::Emitter的运算符,以序列化包含另一个自定义类的向量的自定义类
- 为什么字符串流运算符<<擦除原始值
- 关于使用运算符<<为新手提供C++中的模板
- 我已经完成了<<运算符重载,但它'It’不起作用
- 重载运算符<<输出地址而不是数据成员
- 错误:没有匹配'运算符<<"在'std::cout
- 重载运算符<<用于ostream语法
- 当运算符<存在时,为什么要定义 LT?
- log4cxx访问异常,使用<<运算符和宏
- 重载<<运算符错误C2804:二进制'运算符<<'参数太多