Niko
Niko

Reputation: 257

In C++, how to overload a binary operator in a derived class?

I'm a C++ newbie and this is something I'm running into when doing some practice coding. Say I have a base class that looks like

class base {
public:
    base();
    friend base operator+(const base& lhs, const base& rhs) {
        base result;
        //some calculation
        return result;
    }
};

and a derived class

class derived : base {
public:
    derived();
    friend derived operator+(const derived& lhs, const derived& rhs) {
        // what to write here?
    }
}

Is there an easy way to overload the + operator between two derived class objects? Essentially everything will be the same except I want

derived result;

instead of

base result;

in the first line, so that the constructor of the derived class takes care of some additional initialization of the object. It seems like a common polymorphism feature and I guess there must be an elegant way to do it, but I'm not sure how...

Thanks a lot!

Niko

Upvotes: 4

Views: 586

Answers (3)

n. m. could be an AI
n. m. could be an AI

Reputation: 119887

Binary operators in class hierarchies don't really work. It's OK to experiment and explore but satisfaction is not guaranteed.

One way to make some semblance of working code in this case is to make it into a template.

template <class P>
P operator+ (const P& p1, const P& p2);

class base {
  friend base operator+<> (const base& p1, const base& p2);
};

class derived : public base {
  friend derived operator+<> (const derived& p1, const derived& p2);
};

template <class P>
P operator+ (const P& p1, const P& p2)
{
  P p; 
  // do something
  return p;
}

It is best to put both classes and the operator+ in a namespace so that it does not conflict with other similar operators.

Upvotes: 1

Praetorian
Praetorian

Reputation: 109169

If I understand your question correctly, the friend operator+ defined in derived needs to be identical to that defined in base, except the return type of the latter needs to be derived. One way to do this would be to define a constructor (maybe private) for derived that takes a base argument.

derived(base const& b)
: base(b)
// additional initialization for derived data members
{}

(or take base by value and std::move it to construct the base subobject)

Then, within derived

friend derived operator+(const derived& lhs, const derived& rhs) {
    return static_cast<base const&>(lhs) + static_cast<base const&>(rhs);
}

This will call base's operator+ and then construct a derived instance using the constructor defined above.

Upvotes: 0

R Sahu
R Sahu

Reputation: 206637

Implementing operator+() is riddled with problems when you have to deal with a base class and derived classes.

The best I can think of is implementing a virtual operator+=() member function that returns a reference to the object you are calling the function on.

struct base
{
   // The usual other functions...
   virtual base& operator+=(base const& rhs) = 0;
};

// Provide an implementation in the base class that
// takes care of what can be taken care of in the base
// class.
// This is allowed even when the function is pure
// virtual.
base& base::operator+=(base const& rhs)
{
   // Do the needful.
   // Return a reference to this object.
   return *this;
}

struct derived : base
{
   virtual base& operator+=(base const& rhs)
   {
      // Add checks to make sure that rhs is of
      // derived type.

      // Call the base class implementation to take
      // care of updating base class data.
      base::operator+=(rhs);

      // Take care of updating the data of this object.

      // Return a reference to this object.
      return *this;
   }
};

Then you can use:

base* bPtr1 = new derived;
base* bPtr2 = new derived;
(*bPtr1) += (*bPtr2);

Upvotes: 2

Related Questions