Possible Duplicate:
What’s the right way to overload operator== for a class hierarchy?
In C++, how can derived classes override the base class equality test in a meaningful way?
For example, say I have a base class A. Classes B and C derive from A. Now given two pointers to two A objects, can I test if they are equal (including any subclass data)?
class A {
public: int data;
};
class B : public A {
public: float more_data; bool something_else;
};
class C : public A {
public: double more_data;
};
A* one = new B;
A* two = new B;
A* three = new C;
//How can I test if one, two, or three are equal
//including any derived class data?
Is there a clean way of doing it? What's my best bet?
Thanks!
One way of doing this is to use the
virtual operator==
which takes the base class object as the parameter so that it works properly with different derived objects. However, you need to make this function pure virtual so as to force all the derived objects to implement it. So you will not be able instantiate the base class. For example:I remember reading a succinct description of the public-non-virtual/non-public-virtual idiom and its advantages, but not where. This wikibook has an okay description.
Here is how you apply it to op==:
If you don't care about comparisons of type A to type B, or B to C, etc. then you can simply implement an overloaded equality operator for each class:
That's dangerous though, because if you derive a new class D from B or C, you're going to have problems.
Otherwise you need to implement some comparators with a lot of dynamic_cast<>-ing to really do it right. Alternatively you could implement a function to create a hash code for each object and leverage that, e.g.
If you incorporate the object's type into the hash code in some fashion (not shown above) then you can also dispense with the silly typeid() comparisons above.
Can different derived classes make equal objects?
If so: double dispatch is an option: it does need overloading in the base class, so you will have dependencies
If not: a solution is in the operator==() to check the typeid and return false if they're different. Otherwise call a private equal() function in which the derived class can do a static_cast and compare.
This avoids type-checks in all derived classes
If you don't mind the base class referring to the sub-classes then double-dispatch:
Does it without requiring dynamic_casts.