Operator + overloading in base class and using it

2020-07-24 06:27发布

问题:

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?

回答1:

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.



回答2:

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;

?



回答3:

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.