重载运算符<和运营商>在同一个班

时间:2009-11-07 15:06:18

标签: c++ operator-overloading

在我的作业中,我必须设计一个课程消息;在其他属性中,它具有属性“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)

是否需要声明为成员函数?

谢谢。

3 个答案:

答案 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) …

虽然存在从intRealFraction的隐式转换(使用第一个构造函数)。

另一方面,如果你使用了非成员函数来实现运算符,那么两个比较都可以工作,因为C ++会知道在第一个参数上调用一个隐式构造函数。

答案 1 :(得分:11)

是的,你应该......但是你可以(并且可以说)应该(另外一个)实现三个<><=>= 。这可确保它们的行为一致。通常,<是其他人实施的,因为它是setmap中使用的默认运算符。

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
        //...
    }
};