Reputation: 257
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
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
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
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