#include <iostream>
using namespace std;
#include "Complex.h"

class Base {
public:
  virtual void f( int ) {
    cout << "Base::f(int)" << endl;
  }

  virtual void f( double ) {
    cout << "Base::f(double)" << endl;
  }

  virtual void g( int i = 10 ) {
    cout << "Base::g(int = " << i << ')' << endl;
  }
};

class Derived: public Base {
public:
  void f( Complex ) {
    cout << "Derived::f(Complex)" << endl;
  }

  void g( int i = 20 ) {
    cout << "Derived::g(int = " << i << ')' << endl;
  }
};

int main() {
  Base  b;
  Derived d;
  Base*   pb = new Derived;

  b.f(1.0);    // Base::f(double)

  d.f(1.0);    // Derived::f(Complex)

               // Derived::f(Complex) doesn't overload Base::f -
               // it hides them!! (Base::f(int) and Base::f(double) are not
               // visible in Derived.
               // Complex has an implicit conversion constructor for double
               // ==> Derived::f(Complex(1.0))


  pb->f(1.0);  // Base::f(double)

               // when called through pointer, no hiding. But as compiler
               // has to determine which overloaded function to call
               // at compile time, this decision is based on static type
               // of pointer (here Base)

  b.g();       // Base::g(int = 10)

  d.g();       // Derived::g(int = 20)

  pb->g();     // Derived::g(int = 10)

               // default values are "inserted" by the compiler.
               // again, at compile time only the static type is known
               // (here: Base), so compiler uses this default value .
               // However, the function actually called is determined at
               // runtime (as it is virtual), so Derived::g() is called

               // [RULE] Never change the default parameters of
               //        overridden inherited functions

  delete pb;   // ERROR: compiler generated Base::~Base(pb) is called
               // even if bp is point to a Derived object because
               // destructor is not declared virtual

               // [RULE] Make base class destructors virtual!
}