I have implemented two classes (parent and derived) comparison operator, but testing it I have noticed a confusing behavior in case of using pointers. In addition, I have some other questions about good practices.
Here it is the code:
struct A { int getN() { return _n; } virtual bool equals(A &other) { return getN() == other.getN(); } friend bool operator==(const A &one, const A &other); A(int n) : _n(n) { } private: int _n; }; bool operator==(const A &one, const A &other) { return one._n == other._n; } struct B : public A { friend bool operator==(const B &one, const B &other); B(int n, int m = 0) : A(n), _m(m) { } private: int _m; }; bool operator==(const B &one, const B &other) { if( operator==(static_cast<const A&>(one), static_cast<const A&>(other)) ){ return one._m == other._m; } else { return false; } } int main() { A a(10), a2(10); B b(10, 20), b2(10, 20), b3(10, 30); A *a3 = new B(10, 20); bool x1 = a == a2; // calls A operator (1) bool x2 = b == b2; // calls B operator (2) bool x3 = a == b; // calls A operator (3) bool x4 = b == a; // calls A operator (4) bool x5 = b == *a3; // calls A operator (5) bool x6 = a == b3; // calls A operator (6) bool x7 = b3 == a; // calls A operator (7) return 0; } Questions
Comparing A instances with B ones, the A class operator is called, is this the correct behavior?
The point 5 is the one that seems confusing to me. a3 is declared as A but instanced as B, but the class A operator is called. Is there any way to solve this?
If the operator was implemented as a instance method, depending on it is called with an A object or a B one, the executed method is different. For example:
a == b // executes A::operator== b == a // executes B::operator== I assume that this is confusing and error prone, and must be avoided. Am I right?
const B&is implicitly convertible toconst A&, and the rest is just usual overload resolution. Alsob == a // executes B::operator==, really? I'd expect it not to compile for lack of a suitable overload in B (A::operator==being hidden) or to callA::operator==if there'susing A::operator==inBbool operator==(const B&, const A&)then?operator==as a free function is to avoid the problem about the operands' order.