Search code examples
c++polymorphismoperator-overloadingabstract-class

How do I declare an overloaded operator in an abstract class and override it in a derived non-abstract class?


I'm trying to write an abstract class with some pure virtual binary operators, which should be implemented by the derived class in order to accomplish operator polymorphism. Here's a simplified example:

class Base {
public:
    virtual const Base& operator+ (const Base&) const = 0;
};

class Derived : public Base {
public:
    const Derived& operator+ (const Derived&) const;
};

const Derived& Derived::operator+ (const Derived& rvalue) const {
    return Derived();
}

It doesn't matter right now what the operator does, the important part is what it returns: it returns a temporary Derived object, or a reference to it. Now, if I try to compile, I get this:

test.cpp: In member function ‘virtual const Derived& Derived::operator+(const Derived&) const’:
test.cpp:12:17: error: cannot allocate an object of abstract type ‘Derived’
test.cpp:6:7: note:   because the following virtual functions are pure within ‘Derived’:
test.cpp:3:22: note:    virtual const Base& Base::operator+(const Base&) const

What's wrong? Isn't operator+ (the only pure virtual function in Base) being overriden? Why should Derived be abstract as well?


Solution

  • This kind of overloading is not possible with a normal abstract class in a clean way. First: you should declare + as non member Overload operators as member function or non-member (friend) function?.

    The best you can get is to inherit from a templated interface if you really need this functionality:

    template<typename T>
    class AddEnabled {
      public:
        friend T operator+ (T const& left, T const& right) {
          return left+=right;
        }
    };
    

    Now you write

    class Foo: public AddEnabled<Foo>{
      Foo():mVal(0){
      }
    
      Foo& operator+=(Foo const& foo){
        mVal+=foo.mVal;
      }
    
     private:
      int mVal;
    }
    

    If you comment out Foo& operator+=(Foo const& foo){ you will get a compiler error saying that the operator is not implemented. If you want to know more about the principles involved lookup http://en.wikipedia.org/wiki/Barton%E2%80%93Nackman_trick and http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

    HTH, Martin