So, after reading some SO questions and answers, i still doesn\'t understand why use
friend bool operator==( BaseClass const &left, BaseClass const &righ
There's nothing wrong per se with the member function, but the free function is more generic. The member function is forced to have the left-hand side operand be of type BaseClass
or a child type, while the free function accepts any types that are implicitly convertible to BaseClass
, not just types that are part of the inheritance tree.
Your derived function doesn't have the same signature as the parent operator, so it hides the parent comparison rather than overriding it. This means that you can't make use of the virtual-ness anyway since the static type of the left hand argument determines the function that's called.
That's why the normal method for virtual comparison is a non-member equality operator that dispatches to a virtual comparison function in the base class.
Do consider your specific need for virtual comparison though as it may be a design smell that there's an alternate design you could use instead.
Also note that member comparison (equality in this case) operators should usually be const
.
EDIT: It seems that you may only care about comparison based on the static type of the left hand argument, which should be an easier problem. In this case your code handles all cases except where the left hand argument is a type implicitly converts to a Base
or Derived
by some mechanism other than inheritance (conversion operator or converting constructor). If you don't care about those cases, then the member equality is fine.
As one final note, if the comparison could be done entirely through the public interface, we (almost) always prefer non-member, non-friend functions regardless of whether or not it's an operator.
EDIT2 (A really quick overview of non-member, non-friend):
For example suppose your class has a public key
method, and if the keys of two instances are equal you want to call the objects equal. Then, without using friends or a member equality operator, you can write your equality standalone:
bool operator==(const MyType& left, const MyType& right)
{
return left.key() == right.key();
}
The biggest problem I see with virtual bool operator==( BaseClass const &right )
is that, without multiple dynamic dispatch*, the following assertion will fail.
class Derived1 : public BaseClass {
bool operator==( BaseClass const &right ) override {
return true;
}
}
class Derived2 : public BaseClass {
bool operator==( BaseClass const &right ) override {
return false;
}
}
Derived1 d1;
Derived2 d2;
assert((d1 == d2) == (d2 == d1));
The friend function can be made to handle this, but to be honest, it's a lot of trouble to get something like this right without multiple dispatch. Even with multiple dispatch, proper semantics for such a polymorphic equality operator may not be easy to come up with.
* multiple dynamic dispatch is the ability to do dynamic dispatch on more than one argument, instead of just on this
.
There are two independent points you are trying to make. Firstly, implementing operator as a member function instead of a standalone function. Secondly, implementing it as a virtual function (you even put in in the title).
What are you trying to say by the "virtual" part is not clear. In your code sample the derived class operator does not override base class operator, because their signatures do not match. There's no polymorphism in your example. So, I don't understand what you mean by staying that it "works fine". It doesn't really work at all (as "virtual" operator), since in your code there's really nothing that can "work" yet. At the current moment your code merely compiles, but it doesn't do anything. Provide code that would attempt to demonstrate polymorphic behavior - then we'll see whether it is "working" or not.
As for implementing binary operators as member functions... This matter has been covered more than once already. Binary operators implemented as member functions behave "asymmetrically" with regard to implicit argument conversions. Which is why it is usually a better idea to implement symmetrical binary operators as standalone functions.