#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! }