Polymorphism and Virtual Functions
Compile Time Polymorphism or Early Binding or Static Binding
- An object is bound to its function call at compile time.
- Implemented using overloaded functions and operators
- Main advantage is efficiency
Run Time Polymorphism or Late Binding or Dynamic Binding
- Function calls are not resolved until run time
- Implemented using virtual functions
- Main advantage is flexibility
Virtual Function
- Keyword virtual tells the compiler to enforce late binding of the function when the address of the base class is used
- The inhertance from the base class to the derived class must be public
- A call to a virtual function is resolved according to the underlying type of object for which it is called.
- A call to a non-virtual function is resolved according to the type of the pointer or reference.
- If a function is declared virtual in the base class it is virtual in all derived classes throghout the inhertance hierarchy.
- Virtual function must be member of some class
- Virtual function cannot be a static member function or a global function
- A virtual function that has been defined in a base class need not be defined in the derived class. If it is not, the function defined for the base is called
- It is an error for a derived class function to differ from a base class virtual function in the return type only.
Example:
#include
using namespace std;
class Base // Base class
{
public:
virtual void f1() // Virtual member function.
{ cout << "Called Base::f1()\n"; }
virtual void f2() // Virtual member function.
{ cout << "Called Base::f2()\n"; }
};
class Derived : public Base // Derived class : public inheritance
{
public:
void f1() // Implementation of virtual function - override
{ cout << "Called Derived::f1()\n"; }
void f3()
{ cout << "Called Derived::f3()\n"; }
};
int main()
{
Base *bp = new Derived;
bp->f1();
bp->f2();
// bp->f3(); // Error: Base::f3 not available
cout << "Size of Derived = " << sizeof(Derived) << endl;
return 0;
}
Result:
Called Derived::f1()
Called Base::f2()
Size of Derived = 4 (VPTR)
Mechanism of Virtual Function Call
- Whenever there is one or more virtual function in a class the compiler secretly places a virtual pointer VPTR in the class.
- The compiler secretly inserts code into the beginning of the constructor that initializes the VPTR to point to proper VTABLE.
- When a virtual function call is made through a base class pointer (polymorphic call) the compiler quietly inserts code to fetch the VPTR and look up the function address in the VTABLE, thus calling the correct function and causing late binding to take place.
Function Overriding
- The redefinition of a virtual member function in a derived class with the same signature is called function overriding
Pure virtual function and abstract class
- The use of one or more pure virtual function makes a class abstract, which means that no object can be instantiated from it.
- When an abstract class is inherited, all the pure virtual functions must be implemented, or the inherited class becomes abstract as well.
Syntax:
virtual void pure_virtual_func() = 0;