
Virtual Functions
A virtual member function is a special member function invoked through a public base class reference or pointer. It is bound dynamically at run time. The instance invoked is determined by the class type of the actual object addressed by the pointer or reference.
A virtual function is declared by prefacing a member function declaration with C++ keyword virtual.
The virtual function mechanism allows derived classes to provide different versions of a base class function. Programmer declares a virtual function in a base class, then redefines it in any derived class. A redefined virtual function is said to override the base class function.
When programmer declares a virtual function, she must keep these guidelines in mind:
1) A virtual function can only be a member function.
2) It can be declared a friend in another class.
3) It cannot be a static member, since its call depends on a specific object
for determining which version of the function to invoke.
4) They are accessed by using object pointers.
Example :
class Base
{
public :
virtual void show ( )
{
cout << "base n" ;
}
} ;
class Derived1 : public Base
{
public :
void show ( )
{
cout << "derived1 n" ;
}
} ;
class Derived2 : public Base
{
public :
void show ( )
{
cout << "derived2 n" ;
}
} ;
int main ( )
{
Base b1 ;
Derived1 d1 ;
Derived1 d2 ;
Base * ptr ;
ptr = & b1 ;
ptr->show ( ) ; // execute Base show ( )
ptr = & d1 ;
ptr->show ( ) ; // execute Derived1 show ( )
ptr = & d2 ;
ptr->show ( ) ; // execute Derived2 show ( )
return 0;
}
The output of this program is:
base
derived1
derived2
This is an amazing capability: Completely different functions are executed by the same function call.
virtual Tables
In order to implement dynamic binding, the compiler has to go through some extra steps whenever there is atleast one virtual function within a class. First it creates a table called the virtual function table, usually referred to as the ' vtbl '. This table contains the addresses of all of the virtual functions within the class. The first address occupies position 0, the next position 1, etc. For each derived class, the table is duplicated, and if a virtual function is redefined, then its address replaces the address of the corresponding function from the base class. Any new virtual functions are appended to the end of the table.
Whenever an instance of a class is created, the compiler reserves some extra bytes for use as a pointer to the ' vtbl '. This pointer is referred to as the ' vptr ' or virtual pointer. It is automatically initialized to point to the ' vtbl ' for the class to which it belongs. When you create a pointer of type base and store into it the address of a base or derived instance, and then execute a function using this pointer, the compiler will fetch the address pointed at by ' vptr ' of the invoking instance ( * this ), offset this address by the index of the function in question ( 0 for f ( ) , 1 for g ( ) ) , fetch the address from the ' vtbl ' and execute the function that this address points at.