Search code examples
c++inheritanceoperatorsequalityequals-operator

Equality Test for Derived Classes in C++


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!


Solution

  • 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==:

    struct A {
      virtual ~A() {}
    
      int a;
    
      friend
      bool operator==(A const& lhs, A const& rhs) {
        return lhs.equal_to(rhs);
      }
      // http://en.wikipedia.org/wiki/Barton-Nackman_trick
      // used in a simplified form here
    
    protected:
      virtual bool equal_to(A const& other) const {
        return a == other.a;
      }
    };
    
    struct B : A {
      int b;
    
    protected:
      virtual bool equal_to(A const& other) const {
        if (B const* p = dynamic_cast<B const*>(&other)) {
          return A::equal_to(other) && b == p->b;
        }
        else {
          return false;
        }
      }
    };
    
    struct C : A {
      int c;
    
    protected:
      virtual bool equal_to(A const& other) const {
        if (C const* p = dynamic_cast<C const*>(&other)) {
          return A::equal_to(other) && c == p->c;
        }
        else {
          return false;
        }
      }
    };