Possible Duplicate:
What’s the right way to overload operator== for a class hierarchy?
I have a base class and several derived classes like in the following code:
class Base
{
public:
friend bool operator==(const Base&, const Base&);
virtual ~Base(){}
private:
virtual bool equals(const Base& other) const = 0;
};
bool operator==(const Base& lhs, const Base& rhs)
{
return lhs.equals(rhs);
}
class A : public Base
{
public:
A(int x) : x_(x){}
private:
virtual bool equals(const Base& other) const;
int x_;
};
bool A::equals(const Base& other) const
{
const A* pA = dynamic_cast<const A*>(&other);
if(!pA) return false;
return x_ == pA->x_;
}
class B : public Base
{
public:
B(double y) : y_(y){}
private:
virtual bool equals(const Base& other) const;
double y_;
};
bool B::equals(const Base& other) const
{
const B* pB = dynamic_cast<const B*>(&other);
if(!pB) return false;
return y_ == pB->y_;
}
To be able to compare two derived classes I want to have operator==. The question is how to achieve this in an object oriented way (e.g. respecting encapsulation, maintainability and extensibility). Are there some recommended patterns to do that? Is there an alternative to the above approach avoiding dynamic_cast?
Your way is not perfect. Consider next class deriving from A
:
class AA : public A
{
public:
AA(int x, int y) : A(x), y_(y) {}
private:
virtual bool equals(const Base& other) const;
int y_;
};
bool AA::equals(const Base& other) const
{
const AA* pAA = dynamic_cast<const AA*>(&other);
if(!pAA) return false;
return A::equals(other) && y_ == pAA->y_;
}
then your operatator ==
breaks fundamental rule, it is not symmetrical relation:
A a(1);
AA aa(1,1);
assert(a == aa);
assert(!(aa == a));
Short fix would be to use typeid
:
bool operator==(const Base& lhs, const Base& rhs)
{
return typeid(lhs) == typeid(rhs) && lhs.equals(rhs);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With