Static and Dynamic Polymorphism in c4876
Static and Dynamic Polymorphism in c4876
Overview
Polymorphism means Many forms OO Purists Only virtual methods Liberal C++ guys Either virtual methods (Behavior), or templates (Types), or even function overloading for that matter (Behavior) Generally accepted virtual method based, and template based
Kinds of Polymorphism
Runtime/Dynamic polymorphism (Based on virtual methods) Compile time/Static polymorphism (Based on templates) These 2 are largely orthogonal techniques, but many ways where one could be replaced with the otherand thats where the confusion
Runtime polymorphism
Runtime binding between abstract type and concrete type Enforces a common interface for all derived types via the base class Enforces an Is-A relationship Used extensively in OO frameworks Templates eating into parts of its territory
Non-Intrusive
Weakness of inheritance Base classes dont know the type of their derived classes Static attributes in base class are Shared Weakness of templates They dont lead to an Is-A relationship
Object counter
Synergy again
Base classes need to share the static attributes Use templates to get over that issue One base class generated for each derived class Use inheritance for the Is-A relationship [Whenever the class ctor is called, the base class ctor is called, likewise for the dtor, increment and decrement operations happen automatically]
Illustration
Class Base { public: Base(); virtual void func1(); virtual void func2(); virtual ~Base(): }; Class Derived { public: Derived(); virtual void func1(); virtual ~Derived(); };
Illustration (Contd)
Pointer to Base::func1 Pointer to Base::func2 Pointer to Base::~Base
vtable for the Base class
Illustration (Contd)
Base Object Base Object Base class vtable
Base Object
Derived Object
Derived Object
Derived Object
As we see above, the vptr stored by the compiler in the derived object is looked up, an offset (+1) added to get to the second virtual method in the class, and the function is called
Is that all?
Well, this gets worse when MI (Multiple Inheritance is used) Now, the deal is 15-20% overhead for MI for method defined in the 2nd and onwards base class. Theres no penalty for methods in the first base class we derive from Ensure your most frequently called methods are from the FIRST base class you derive from if you use MI, order your base classes accordingly
Workaround
To reduce compile times, we can use the Explicit instantiation technique in cases where large includes are warranted Here basically you give the method body in a .cpp file and put only the template class definition in the .h file, but explicitly instantiate the template in the .cpp file where the methods are defined for all types expected
Summary
Prefer inheritance when
You want to reuse code/structure from the base class You want to develop OO frameworks which need to store heterogeneous elements in their data structures