James
James

Reputation: 2999

c++ how to inherit operator that returns specific type

I have a class 'A' that overrides the + operator, and a subclass 'B'.

I want to inherit 'A's + operator but instead of returning type A I want to return type B.

How can I go about doing this? I tried calling the parent's operator from B and casting the result to an A object but it won't let me cast a parent to a child

Can my + operator somehow return a generic 'A' pointer or something?

Upvotes: 4

Views: 404

Answers (3)

Mooing Duck
Mooing Duck

Reputation: 66922

I frequently see it done in the following way:

class A {
    int a;
    A(int rhs) :a(rhs) {} 
public:
    A& operator+=(const A& rhs) {a+=rhs.a; return *this} 
    A operator+(const A& rhs) {return a+rhs.a;} 
};

class B : public A {
    int b;
public:
    B(const B& rhs) :A(rhs), b(rhs.b) {}
//                               VVVVVVVVVVVVVVVVVV
    B& operator+=(const B& rhs) {A::operator+=(rhs); b+=rhs.b; return *this;}
    B operator+(const B& rhs) {return B(*this)+=rhs;}
};

Upvotes: 2

Xavier Holt
Xavier Holt

Reputation: 14619

It could - no technical reason it couldn't - it just violates some expectations when using operators. So if this is code for yourself, go for it, but if it's going to be read or used by other people, I'd reconsider for the following reasons:

  1. Expected behaviour is that operators like += and *= return a reference to the object they were called on after modifying that object. Operators like + and * return a new object (they pretty much have to, as the implication is that the object they're called on isn't changed). They don't return a pointer to a new object because:
  2. No one expects them to, so they won't think to delete an object they get back from an operator, which will cause memory leaks, and:
  3. You can't chain operators that return pointers; an expression like MyClass a = b + c + d; won't work, because the return type (MyClass*) won't match the argument type you need to pass into the operator (probably const MyClass&).
  4. Returning a reference to a new object lets you work around #3, and still supports polymorphism, but you're still stuck with #2, and that's the worse of the pair. The same applies to overloading the operator to take either a pointer or a reference.

Ultimately, just do whatever makes life easiest for whoever's going to be using the code - and if it's just you, you can do anything you want. Just be careful if it's going to fall into other people's hands, because they will make assumptions.

Hope this helps!

Edit: An example that returns a reference to a new object:

A& A::operator + (const A& other) const
{
    A* temp = new A(); // <- This is why it's a potential memory leak
    /* Do some stuff */
    return *temp;
}

But, having had a little more time to think about this, I'd propose an alternative: Define an = operator for B that takes an A as its argument. Then you could do things like this:

B b1;
B b2;
B b3 = b1 + b2;

And it wouldn't matter that b1 + b2 returned an A, because it was converted back to a B during the =. If this works for you, I'd recommend it above any other method, as it lets all the operators have expected behaviours.

Upvotes: 2

Mark B
Mark B

Reputation: 96251

The simplest way to solve this problem is to implement operator+ in terms of operator+=. So roughly:

A::operator+=(const A& right) { /* stuff */ }
B::operator+=(const B& right) { static_cast<A&>(*this) += right; /* stuff */ }
operator+(B left, const B& right) { return B += right; }

Upvotes: 1

Related Questions