Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading both operator< and operator> in the same class

In my homework, I have to design a class Message; among other attributes, it has attribute "priority" (main goal is to implement priority queue).

As in container I must check if one object is greater than other, I have overloaded operator '>'. Now, I have a few general questions about it...

Question one:

If I overload operator '>', should I overload operator '<' for arguments (const Message&, const Message&)?

My opinion is that overloading both > and < and using it in code will generate an error:

if(message1 > message2)
   { ... }

(Does the following code calls operator > for message1 object, or operator < message2 object?)

But, what if I use operator like this:

if(message1 < message2)
   { ... }

?

operator> is declared as friend function:

friend bool operator>(const Message& m1, const Message& m2)

Does it need to be declared as member function?

Thank you.

like image 239
Nemanja Boric Avatar asked Nov 07 '09 15:11

Nemanja Boric


1 Answers

If I overload operator '>', should I overload operator '<' for argumenst (const Message&, const Message&)?

Yes. In fact, it’s convention in most code to prefer the usage of < over > (don’t ask me why, probably historical). But more generally, always overload the complete set of related operators; in your case, this would probably also be ==, !=, <= and >=.

(Does the following code calls operator > for message1 object, or operator < message2 object?)

It always calls what it finds in the code. For the C++ compiler, there’s absolutely no connection between > and <. For us, they look similar but the compiler sees two completely different, unrelated symbols. So there’s no ambiguity: the compiler calls what it sees.

Does it need to be declared as member function?

No. In fact, it’s best not declared as a member function. Declaring it as a member function means that the first argument (i.e. the left-hand side of the expression) must really be a Message object, rather than an object that is implicitly convertible to a Message.

To understand this, consider the following case:

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

Now you can write the following comparison:

int x = 1;
RealFraction y = 2;
if (y < x) …

but you cannot write the following:

if (x < y) …

although there exists an implicit conversion from int to RealFraction (using the first constructor).

If, on the other hand, you had used a non-member function to implement the operator, both comparisons would work because C++ would know to call an implicit constructor on the first argument.

like image 140
Konrad Rudolph Avatar answered Oct 12 '22 15:10

Konrad Rudolph