I have 2 classes, base (with copy constructor) and derived, in base Ι have overloaded operator+
:
class Base {
public:
Base(const Base& x) {
// some code for copying
}
Base operator+(const Base &bignum) const {
Base x;
/* ... */
return x;
}
};
class Derived : public Base {
};
And when i try to do something like that
Derived x;
Derived y;
Derived c=x+y;
I get error: conversion from "Base" to non-scalar type "Derived" derived
Could problem be in that operator + returns object of Base
type and I want assign it to Derived
type object?
In fact you don't need to redefine the operator+
(unless your design requires it, as Ajay's example pointed out).
It works better than you think
Take the following minimalistic example:
struct Base {
Base operator+ (Base a) const
{ cout <<"Base+Base\n"; }
Base& operator= (Base a)
{ cout<<"Base=Base\n"; }
};
struct Derived : public Base { };
int main() {
Base a,b,c;
c=a+b; // prints out "Base+Base" and "Base=Base"
Derived e,f,g;
e+f; // prints out "Base+Base" (implicit conversion);
}
This works perfectly, because when encountering e+f
the compiler finds operator+
of the base class, and he implicitly convert from Derived
to Base
, and computes a result which is of type Base
. You could easily write c=e+f
.
What's missing ?
The problem starts only with the assigment to a Derived. As soon as you try g=e+f;
you will get an error. The compiler doesn't know for sure how to put an A into a B. This prudence is justified by common wisdom: All apes are annimals, but all animals are not necessarily apes.
And this is even more obvious if Derived
has more fields than Base
: how should teh compilier initialise them ? Basically, how to tell the compiler how he shall make a Derived
out of something else ? With a constructor !
struct Derived : public Base {
Derived()=default;
Derived(const Base& a) : Base(a) { cout<<"construct B from A\n"; }
};
Once you have defined this, everything works as you'd expect:
g=e+f; // will automatically construct a Derived from the result
// and then execute `Derived`'s default `operator=` which
// will call `Base`'s `operator=`
Here a live demo.
This is not a correct design. Consider a class Point2D
having x
and y
, and Point3D
class which is inheriting from Point2D
having additional member z
. Do you thing following will help?
Point2D operator+(const Point2D &pt) const;
When called as:
Point3D a, b;
Point3D c = a+b;
?
Yes, this is exactly the problem. The plus operator is only guaranteed to return a Base object, so you can assign it to a Base object. All Derived objects can be substituted for Bases, but not the other way.