Jump to

v05-l2-codeOutput2

What is the output of the following code ?

#include <iostream>
using std::cout, std::endl;

class Hamburger {
public:
    virtual void meet(Hamburger other) {
        cout << "Moin "; other.salute();
    }
    virtual void salute() { cout << "Moin"; }
};

class French: public Hamburger {
public:
    virtual void meet(Hamburger& other) {
        cout << "Bonsoir "; other.salute();
    }
    virtual void salute() { cout << "Bonsoir"; }
};

int main() {
    French pelu; French ehlu; Hamburger alex;
    pelu.meet(alex); alex.meet(ehlu);
}

???

When looking at those kind of codes (polymorphism), use this generic approach :

  1. what is the type of the variable calling the method ?
  2. it's a "plain" type (no pointer nor reference) => call the method of the class
  3. it's a reference or a pointer => go to 2.
  4. what's the "real" class of your instance ?
  5. same class : call the method of the class
  6. child class : go to 3.
  7. is the method overridden in the "real" class (same signature as in the parent class) ?
  8. yes : call the overridden method
  9. no : look up in the parent(s) class(es) up to finding an overridden method and use it

So, for the example above, you have to apply this systematically :

pelu.meet(alex)

=> plain type (French pelu), call French::meet => Bonsoir in first and then

other.salute()

=> reference (Hamburger& other = alex) => the real class is Hamburger (Hamburger alex) => call Hamburger::salute => Moin in second

alex.meet(ehlu)

=> plain type (Hamburger alex) => call Hamburger::meet => Moin in third and then

other.salut()

=> plain type (Hamburger other = ehlu ... call by value !) => call Hamburger::salute => Moin in fourth

=> Bonsoir Moin Moin Moin

Of course, if the reference was not missing for other in Hamburger::meet(Hamburger other), then dynamic binding would have been used and the last call would have been French::salute, so a Bonsoir in fourth.