0

I'm looking for an elegant solution to the following "problem":

Consider the classes Base and Child, and the way operator+ works here:

class Base
{
public:
    Base(int a=0) : mValue(a) {};
    Base(const Base& rhs) : mValue(rhs.mValue) {};
    Base& operator=(const Base& rhs) {
        if (this==&rhs) return *this;
        mValue=rhs.mValue;
    }


    friend const Base operator+(Base &lhs, Base &rhs);

private:
    int mValue;
};

const Base operator+(Base &lhs, Base &rhs)
{
    Base result(lhs.mValue+rhs.mValue);
    return result;
}

class Child : public Base
{
public:
    Child(int a=0) : Base(a) {};
};

int main()
{
    Child a(2);
    Child b(5);
    Child c(a+b);  // **** This line ****
            Child d;
            d=(a+b); // **** or this other one ****

}

The marked lines in main give the error: cannot convert from 'const Base' to 'Child'

I understand perfectly that the operator has been defined in the Base class, and returns an object of type Base, which can't be converted to Child. One solution is overloading operator+ for the Child class, but I am wondering whether there is a better, less costly method. I'm under the impression that I'm forgetting a much easier option. Thanks!

DrD
  • 419
  • 4
  • 14
  • Sorry, typo :) Now corrected – DrD Mar 19 '14 at 13:18
  • Why does `operator=` not return anything? Does it even compile? Also read up on the [copy-swap-idiom](http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom) – andre Mar 19 '14 at 13:29
  • @andre - The asignment operator is not the problem. I have updated the question to reflect this. The problem is the same for *c* and *d*: *operator+* returns a *Base* object, not a *Child* object. – DrD Mar 19 '14 at 13:34
  • If thats the case you should only need to add the copy constructor `Child(const Base& other) : Base(other) {...};` – andre Mar 19 '14 at 13:36
  • Actually, that was suggested by rajenpandit a few minutes ago, but I missunderstood it. It actually works! Thank you very much! – DrD Mar 19 '14 at 13:42

3 Answers3

1

you can define a constructor Child(Base& obj) then Child c=(a+b); statement will be fine and then you can use the base object as per your requirement.

rajenpandit
  • 1,265
  • 1
  • 15
  • 21
  • 2
    Instead of Child(Base& obj), it should be Child(const Base& obj) : Base(obj) { }; – Bill Perkins Mar 19 '14 at 13:40
  • Apologies rajenpandit, I actually made a mistake when I tried your suggestion. It works, so thank you very much! – DrD Mar 19 '14 at 13:43
  • @Bill Perkins - Thank you, that is exactly what I tried (rajenpandit omitted the *const*, but actually I left it there because it is what I need) – DrD Mar 19 '14 at 13:44
1

There is no easier option.

Operator overloading and class hierarchies don't really like to mix. I'm personally very suspicious when a type that should be a value type (or else why are you overloading operators?) is part of a hierarchy. Can you describe your actual architecture? Does it actually make sense to overload the operator there?

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
  • The actual classes are a bit more complex than a simple wrapped int, but the principle is the same as in the example. Both base and derived classes need an *operator+*, with identical functionallity, only that in the derived class it returns a derived object. – DrD Mar 19 '14 at 13:37
  • What do these classes represent that makes them need the operator and yet puts them in an inheritance relationship? – Sebastian Redl Mar 19 '14 at 13:41
  • They are matrices, the derived class is an special type of the Base class. – DrD Mar 19 '14 at 13:49
0

If you want to build a child from a base without adding the appropriate constructor, there is another alternative. You can declare the casting operator in your base class, returning your mValue :

operator int() const;

This way, the compiler will do the job implicitly.

PS : Ensure const-correctness of your additive operator :

friend Base operator+(const Base &lhs, const Base &rhs);
Kiwi
  • 2,698
  • 16
  • 15