0

I have a hierarchy of classes, where I have to overload operator+ and operator- so that it produces a new type like so.

Animal * pg = new Pigeon();
Animal * pgone = new Pigeon();

Animal * babypigeon = *pgone + *pg;

Where Animal is the base type and Pigeon is a derived type. I wondered if I should just overload the operators on the derived type or do I need to overload the base type's operators too?

Assuming that all derived types will be created using a base pointer.

Tony The Lion
  • 61,704
  • 67
  • 242
  • 415

4 Answers4

3

Your logic is off and your program will not do what you expect it to do. You're adding pointers there. The + operator will not be called.

You need something like

babypigeon = (*pgone) + (*pg);

In which case, you're adding two Animals. So your + operator has to be overloaded in the Animal class.

A solution to this would be to call some virtual methods from the + operator and have the logic there.

EDIT:

class Animal{
//....
    virtual Animal plusLogic( const Animal& otherAnimal ) const;
    Animal operator + ( const Animal& otherAnimal ) const
    {
        return this->plusLogic(otherAnimal);
    }
}

class Pigeon : public Animal{
//.....
    virtual Animal plusLogic( const Animal& otheAnimal ) const;
}
Animal Pigeon::plusLogic (const Animal& otherAnimal) const
{
    //logic heree
}

That way, calling the + operator on an Animal which is of type pigeon will call the function plusLogic in class Pigeon (since it is virtual).

sbi
  • 219,715
  • 46
  • 258
  • 445
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • can you show me a simple example of the virtual methods solution you suggest? – Tony The Lion Aug 08 '11 at 13:30
  • I know this is a common idea to circumvent the problems arising from this kind of setup, but it doesn't make much sense. For one, why have the operator delegate to a virtual function, rather than making it virtual itself? The only reason I can see is a (sensible) shyness to mix polymorphism with operator overloading, but hiding it behind a delegation won't help the underlying problems. Plus this still doesn't answer how you should implement `Pigeon::plusLogic()`, a problem that pokes at the heart of the matter. Doing what Tony wants is ill-fatedm and should be avoided. See my answer. – sbi Aug 09 '11 at 06:05
  • Also, _if_ you do this, at least make the left argument of `operator+` (`this` in your case, although that operator [should be a free function, not a member](http://stackoverflow.com/questions/4421706/operator-overloading/4421729#4421729)) `const`. I went in to fix that in your answer. – sbi Aug 09 '11 at 06:08
  • I know what you mean, however, whenever I ask a question on stackoverflow, I expect answers that help me achieve what I want to achieve and then let me figure out on my own if the solution is suited for me or not. I don't like answers like "Just don't do it". I think the op knows he could have written a function, and now just wants to know if he can do the same thing using an operator. Therefore, my answer. I would also use a function for this. The exact logic implementation is besides the point, I have a feeling he already knows how to do that. – Luchian Grigore Aug 09 '11 at 06:09
2

You can't do that- pgone and pg are pointer types and cannot have operators overloaded for them. You would have to have

Animal* baby = *pgone + *pg;

In that case, you would need a double dispatch system to cover all the cases, and I also hope that you never wanted to use these types as values. I hope that you don't have too many derived types too because that could rapidly become nasty.

Puppy
  • 144,682
  • 38
  • 256
  • 465
1
  • you may not overload operators for pointer types, so your code should not compile (Edit: the question has been modified and the should not compile part is no more valid),

  • in general operator overloading work best with non polymorphic type:

    • see the restriction above,
    • with polymorphic type, you often need multiple distpatch to be able to do something meaningfull
    • returning a polymorphic value has its own problem (who is the owner if one need to allocate something), increased by the fact that operators drives to be combined (a+b+c)
    • a potential solution is the letter/enveloppe idiom
AProgrammer
  • 51,233
  • 8
  • 91
  • 143
1

I see several very basic problems with this approach:

  1. There is no universally agreed-upon operator for mating pigeons (really, wouldn't it be better expressed using * rather than +?), so this clearly violates the first basic rule of operator overloading.
    Although @Alexandre made a joke, he does have a good point in his comment: rather use a well-named function.

  2. Operator overloading is something that's well-suited for value types, and ill-suited for polymorphic types. It doesn't make any sense to mate any two animals.
    You can't generically specify the (dynamic) type of the result, because you'd have to create a new type for each permutation, thereby creating even new possible permutations, resulting in an endless proliferation of types. (And also you might have the animal protection leagues at your heels if you try to, and they can be pretty annoying.)

  3. The operator as used by your example takes two objects by reference, but would have to return a pointer to a dynamically allocated object. That not only sounds terribly wrong, it also is.
    For starters: Now you cannot chain addition anymore (pg1 + pg2 + pg3, because the result of addition isn't of the same type as its operands. That's very counter-intuitive and violates the second basic rule of operator overloading.
    And I won't even touch questions like who owns the returned object, and who is responsible for cleaning it up.

So the outcome of this is: Just don't do this. And I don't find that surprising, because over the years I have learned that this is the usual outcome if you try to apply operator overloading in such setups.

Community
  • 1
  • 1
sbi
  • 219,715
  • 46
  • 258
  • 445