在我的作业中,我必须设计一个课程消息;在其他属性中,它具有属性“priority”(主要目标是实现优先级队列)。
在容器中,我必须检查一个对象是否大于其他对象,我重载了运算符'>'。现在,我有一些关于它的一般性问题......
问题一:
如果我重载运算符'>',我应该重载运算符'<' for arguments(const Message&,const Message&)?
我的意见是超载>和<并在代码中使用它将生成错误:
if(message1 > message2)
{ ... }
(以下代码是否为message1对象调用运算符>或者运算符< message2对象?)
但是,如果我使用这样的运算符怎么办:
if(message1 < message2)
{ ... }
?
运营商GT;被声明为朋友功能:
friend bool operator>(const Message& m1, const Message& m2)
是否需要声明为成员函数?
谢谢。
答案 0 :(得分:24)
如果我重载运算符'&gt;',我应该重载运算符'&lt;' for argumenst(const Message&amp;,const Message&amp;)?
是。事实上,在大多数代码中,更倾向于使用<
而不是>
(不要问我原因,可能是历史)。但更一般地说,总是超载整套相关的运营商;在您的情况下,这可能也是==
,!=
,<=
和>=
。
(以下代码是否为message1对象调用运算符&gt;或者运算符&lt; message2对象?)
它始终调用它在代码中找到的内容。对于C ++编译器,>
和<
之间绝对没有联系。对我们来说,它们看起来很相似,但编译器看到两个完全不同的,不相关的符号。所以没有歧义:编译器调用它看到的内容。
是否需要声明为成员函数?
没有。实际上,最好不要声明为成员函数。将其声明为成员函数意味着第一个参数(即表达式的左侧)必须确实是Message
个对象,而不是可隐式转换为Message
的对象。 / p>
要理解这一点,请考虑以下情况:
struct RealFraction {
RealFraction(int x) { this.num = x; this.den = 1; }
RealFraction(int num, int den) { normalize(num, den); }
// Rest of code omitted.
bool operator <(RealFraction const& rhs) {
return num * rhs.den < den * rhs.num;
}
};
现在您可以编写以下比较:
int x = 1;
RealFraction y = 2;
if (y < x) …
但无法撰写以下内容:
if (x < y) …
虽然存在从int
到RealFraction
的隐式转换(使用第一个构造函数)。
另一方面,如果你使用了非成员函数来实现运算符,那么两个比较都可以工作,因为C ++会知道在第一个参数上调用一个隐式构造函数。
答案 1 :(得分:11)
是的,你应该......但是你可以(并且可以说)应该(另外一个)实现三个<
,>
,<=
,>=
。这可确保它们的行为一致。通常,<
是其他人实施的,因为它是set
和map
中使用的默认运算符。
E.g。如果您实施了<
,则可以像这样定义>
,<=
和>=
。
inline bool operator>(const Message& lhs, const Message& rhs)
{
return rhs < lhs;
}
inline bool operator<=(const Message& lhs, const Message& rhs)
{
return !(rhs < lhs);
}
inline bool operator>=(const Message& lhs, const Message& rhs)
{
return !(lhs < rhs);
}
==
和!=
通常是单独实施的。有时类会实现==
,a == b
当且仅当!(a < b) && !(b < a)
但有时==
被实现为比!(a < b) && !(b < a)
更严格的关系时。但是,这样做会导致类的客户端更加复杂。
在某些情况下,可以接受<
,>
,<=
和>=
,但不能==
或!=
。< / p>
答案 2 :(得分:5)
如果赋值没有明确要求使用运算符重载,您还可以考虑使用函数对象。原因是可能有不止一种方法来比较两个消息“少于”(例如按字典比较内容,发布时间等),因此operator<
的含义不直观清晰。
使用std::priority_queue
将要使用的函数对象指定为第三个模板参数(遗憾的是,您还需要指定第二个 - 基础容器类型):
#include <queue>
#include <string>
#include <functional>
#include <vector>
class Message
{
int priority;
std::string contents;
//...
public:
Message(int priority, const std::string msg):
priority(priority),
contents(msg)
{}
int get_priority() const { return priority; }
//...
};
struct ComparePriority:
std::binary_function<Message, Message, bool> //this is just to be nice
{
bool operator()(const Message& a, const Message& b) const
{
return a.get_priority() < b.get_priority();
}
};
int main()
{
typedef std::priority_queue<Message, std::vector<Message>, ComparePriority> MessageQueue;
MessageQueue my_messages;
my_messages.push(Message(10, "Come at once"));
}
实现自己的优先级队列时,可以通过以下方式进行处理:
class MessageQueue
{
std::vector<Message> messages;
ComparePriority compare;
//...
void push(const Message& msg)
{
//...
if (compare(msg, messages[x])) //msg has lower priority
//...
}
};