George
George

Reputation: 3845

c++ overloaded method in derived class

I have the following question:

Assume base class A with method:

A& operator+(A& a) {...}

I also have a derived class B which overloads (or at least it should so) this method:

A& operator+(B& b) {...}

The problem is that if i want to call something like: b + a (where b is of type B and a of type A) i get a compile error. (error C2679: binary '+' : no operator found which takes a right-hand operand of type 'A' (or there is no acceptable conversion)).

Shouldnt that call the base class method? (it looks like it overrides the method..) If not, why? Is there a way to fix this (dont tell me to overload the method in B with A&)

Sorry i dont give examples in formated text, but i dont know how to format it.

Thanks in advance!

PS Im using Visual studio 2010 beta.

Upvotes: 4

Views: 1690

Answers (4)

Mark Ransom
Mark Ransom

Reputation: 308121

The problem is called hiding - a member function in a derived class hides functions with the same name in the base class. In this case you can't access A::operator+(A&) because it's being hidden by B::operator+. The way to fix this is to define B::operator+(A&), and possibly have it call the base class function.

Edit: There's a section in the C++ FAQ Lite that goes into more detail about this problem and offers another possible solution, namely the using keyword.

Upvotes: 3

Nikolai Fetissov
Nikolai Fetissov

Reputation: 84159

The problem is that you are defining the member operator, so when called as b + a it results in b.operator+( a ), which doesn't exist.

Accepted practice is to define free operators that themselves would call [virtual] members on the arguments.

Edit:

Standard example of what I'm talking about is adapting a class hierarchy for output streaming:

class base
{
public:

  virtual ~base();
  virtual void print( std::ostream& ) const;
};

std::ostream& operator<<( std::ostream& out, const base& b )
{
  b.print( out ); return out;
}

This doesn't really work for math operations since you want to return by [const] value, not reference, i.e. avoid nonsense like a + b = c;.

For example, addition of real and complex numbers is defined, but yields complex number as the result, so you cannot derive complex from real. The other way - maybe. But still you want to define exact operations interface:

const real operator+( const real&, const real& );
const complex operator+( const complex&, const complex& );

Hope this gives you enough to re-think your design :)

Upvotes: 2

Steve Jessop
Steve Jessop

Reputation: 279225

No, it won't call the base class function. Class B has an operator+, it doesn't take the correct parameter, end of story.

You can define operator+ as a free function, not in any class. Perhaps a friend, if it needs to access private data:

A operator+(const A &lhs, const A &rhs) { ... }
B operator+(const B &lhs, const B &rhs) { ... }

Then b + a will call the first operator, as will a + b. b + b will call the second.

Alternatively, you could "un-hide" the base class implementation, by putting this in class B:

using A::operator+;

it's probably best not to, though. Most operators work better as free functions, because then you get automatic conversions on both operands. C++ never performs conversions on the LHS of a member function call.

Btw, operator+ almost certainly should return by value, not by reference, since an automatic (stack) variable no longer exists once the function returns. So the caller needs to be passed a copy of the result, not a reference to it. For this reason operator+ and inheritance aren't a great mix, although it can probably work as long as the caller knows what they're doing.

Upvotes: 4

David Gladfelter
David Gladfelter

Reputation: 4213

Couple of things come to mind. First, you would generally want to make the operator + "virtual". Then, the derived operator + taking a reference to B would be an override due to co-variance, instead of hiding the base class implementation, which is what is happening here.

That said, I suspect (but can't say for certain without compiling a test project) that that would actually solve your problem. That's because the standard answer for binary operators is to use static methods that take two parameters on the class. The C++ STL uses this technique extensively, and I don't know of a reason to attempt to implement binary operators as instance methods, virtual or not. It's just too confusing, with no real up-side.

Upvotes: 0

Related Questions