Virtual Functions in C++

Important points about Polymorphism and Virtual Function

 

  • Polymorphism is the third important feature in C++ after data abstraction and inheritance.
  • Polymorphism means single name and multiple meaning.
  • There are two types of polymorphism like compile time polymorphism and run time polymorphism.
  • We can achieve compile time polymorphism using the function and operator overloading.
  • We can achieve run time polymorphism using the virtual functions.
  • In case of function overloading we can write the multiple function having same name inside a single class. And when we call that function the call is bind with the appropriate definition at the compilation time.
  • Binding the definition at the compile time is the concept which is used in the procedural language like C.
  • Such type of binding the function call with that appropriate definition of the function is called as early binding. C uses early binding only.
  • On the other hand function call is bind with the appropriate definition at run time it is called as Run time polymorphism or late binding.
  • Late binding in C++ is achieved with the help of Virtual Function.
  • To create a function virtual just write the virtual keyword before the declaration of the function in the base class. Like

 

virtual int Fun( int i , int j ){ }

 

  • If function is declared virtual in base class then it is virtual in its all derived class.
  • Redefination of virtual function in derived class is called as function overriding.
  • From the virtual keyword compiler decides to perform the late binding.
  • To perform the late binding compiler will create a single table for wach class and that table is called as Virtual table(VTABLE).
  • VTABLE contains all the addresses of the virtual functions for the particular class.
  • Address of that VTABLE is kept inside each class and the pointer which stores the address of VTABLE is called as VPTR. All this task is done by the compiler itself.
  • Because of which size of object of class which contains virtual function is 4 byte more that the actual data members. This 4 bytes is used for VPTR. VPTR is the first member in the object layout.
  • Problem which occurs due to early binding : When base class pointer points to the derived class object and when we call some method using that pointer then always method of base class is invoked because compiler binds the definition of the class whose pointer is used for calling the function. But when we make the base class function virtual then the function of the class whose address is assigned to the base class pointer is called. This binding of call with function definition is done at runtime with the help of VTABLE.
  • When we make a virtual function call through base class pointer compiler inserts code to fetch VPTR and lookup the function address in the VTABLE, thus calling the correct function and causing late binding taking place.
  • In VTABLE compiler places addresses of virtual functions of base class. And in derived class’s VTABLE compiler places same addresses as the base class , but if the derived class override that virtual method in that case compiler replace the address of base class method with the new method. This task is done at the compile time only.
  • In VTABLE addresses of functions are kept in the order in which they are defined in the base class. Means if we define a function at second position then address of that function is found at VPTR+2 position.
  • In normal function calling sequence compiler generate simple CALL instruction with appropriate address of that function.But in case of virtual functions compiler generates instruction as CALL the function at address VPTR+2. Because fetching the VPTR and determination of actual function address occurs at runtime.

 

VirtualFunctions in C

 

Example of Virtual Function:

 

Class Base

{

public:

int I,j;

 

virtual void fun()

{

cout<<”In Base class function”;

}

};

 

class Derived : public Base

{

public:

void fun()

{

cout<<”In Derived class function”;

}

};

 

int main()

{

Base *bptr;

Derived dobj;

bptr = dobj;

bptr->fun();

return 0;

}

 

  • In this example we have two classess named as Base and Derived.Derived class is derived from class base.
  • Base class contains virtual method fun.Derived class provides its own definition for method fun means it is a overriding.
  • When we remove the virtual keyword from the base class defination function of base class is called because in that case early binding is occurs and compiler decides the appropriate function depends upon the pointer type.
  • But when we declare a function virtual then function of derived class is called, because base class points to the derived class object.
  • Suppose address of fun in base class is 1100 and fun of derived class is 1500.VTABLE of base class contains address as 1100 as the first entry in the VTABLE and VPTR contains the starting address of that VTABLE.
  • In Derived class we provide another definition of function fun hence in the VTABLE of derived class overrides the address 1100 and make it as 1500.

 

The assembly code for bptr->fun(); is

push si

mov bx, word ptr [si]

call word ptr [bx]

add sp, 4

 

  • si contains address of derived class object which is pushed at the time of calling member function(And it is this pointer). At the start of object there is VPTR and in VTABLE first method is our expected method.
  • Creating a VPTR and initialize that VPTR with the appropriate VTABLE is done inside the constructor.
  • If we are not provide the constructor explicitely in that case compiler provides its default constructor and perform the other tasks.
  • Important thing in the runtime polymorphism is that the late binding is valid only if we call the function using addressess but if we call the function with the object directly then compiler can easily determine the address of the function and it performs the early binding.

 

class base {

public:

virtual void demo()

{

cout<<in the base class;

}

};

 

class derived : public base {

public:

void demo()

{

cout<<Inside the derived class;

}

};

 

int main()

{

derived dobj;

base * pbobj = &dobj;

base & rbobj = dobj;

base obj;

// Late binding for both:

pbobj->demo();

rbobj.demo();

// Early binding

obj.demo();

}

 

output:-

Inside the derived class

Inside the derived class

in the base class

 

  • in the above example when we call demo function by using pbobj or rbobjthe function of derived class is callled because the virtual function(late binding)mechanism is used there.

But when we call by using the obj as a base class object function of base class is called because there is no ambiguty for the compiler.compiler gets appropriate address of function from the object.

For more reading about technology news in singapore and seo to online marketing do view more about other pages.

Sourabh Bhunje

Sourabh Bhunje, B.E. IT from Pune University. Currently Working at Techliebe. Professional Skills: Programming - Software & Mobile, Web & Graphic Design, Localization, Content Writing, Sub-Titling etc. http://techliebe.com/about-us

Leave a Reply