Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement operator== for polymorphic classes in c++ [duplicate]

Tags:

c++

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?

like image 333
MWid Avatar asked Oct 24 '12 08:10

MWid


1 Answers

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);
}
like image 166
PiotrNycz Avatar answered Oct 24 '22 02:10

PiotrNycz