Classes and Objects
#include
using namespace std;
class complex // class definition
{
int i;
int j;
public:
//member functions
complex() //default constructor initialzed values with ' 0 ' as not to have garbage values
{
i = 0 ;
j = 0 ;
}
complex(int a, int b) // constructor initializing the values (parameterized constructor )
{
i = a;
j = b;
}
complex operator+ (complex c) // operator overloading to perform sum of complex numbers
{
complex temp; // creating a local object to store result
// adding local data member ( with the help of this pointer ) and parameter object data member (accessing with dot member access operator)
temp.i = this->i + c.i; //adding real part
temp.j = this->j + c.j; //adding imaginary part
return temp;
}
void show() // function to print complex number
{
cout<<"Complex Number: "<<i<<" + i * "<<j;
}
};
int main() //main function
{
complex c(4,5),d(6,7) , e ; // creating objects
e = c+d ; // addding two complex numbers
e.show() ;
}
Output :

2) Virtual functions and runtime polymorphism and how a vtable works with an example in code :
Virtual function :
A virtual function is a member function which is declared within a base class and is re-defined (overridden) by a derived class. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class’s version of the function. virtual key word tells the compiler to perform late binding where the compiler matches the object with the right called function and executes it during the runtime. This technique of falls under Runtime Polymorphism.
- Virtual functions ensure that the correct function is called for an object, regardless of the type of reference (or pointer) used for function call.
- They are mainly used to achieve runtime polymorphism .
- Functions are declared with a virtual keyword in base class.
- The resolving of function call is done at runtime.
Runtime polymorphism :
The term polymorphism means the ability to take many forms. It occurs if there is a hierarchy of classes that are all related to each other by inheritance. In simple words, when we break down Polymorphism into ‘Poly – Many’ and ‘morphism – Forms’ it means showing different characteristics in different situations.

Runtime polymorphism is achieved only through a pointer (or reference) of base class type. Also, a base class pointer can point to the objects of base class as well as to the objects of derived class. In below code, base class pointer *t contains the address of object 'c' of derived class.
Late binding (Runtime) is done in accordance with the content of pointer (i.e. location pointed to by pointer) and Early binding (Compile time) is done according to the type of pointer, since gets() function is declared with virtual keyword so it will be bound at runtime (output is 9 as pointer is pointing to object of derived class) and speak() is non-virtual so it will be bound during compile time (output is 333 as pointer is of base type).
The main thing to note about the program is that the derived class’s function is called using a base class pointer.The idea is that virtual functions are called according to the type of the object instance pointed to or referenced, not according to the type of the pointer or reference.In other words, virtual functions are resolved late, at runtime.
#include
class animal
{
public :
virtual int gets() {return 1 ;}
int speak() {return 333;}
} ;
class cat : public animal
{
int gets() {return 9 ;}
int speak() {return 999;}
int speak2() {return 333;}
} ;
int main()
{
cat c ;
animal *t = &c ;
//run time binding
std::cout<gets()<speak2()<speak()<
Output :

Vtable :
if a class contains a virtual function then compiler itself does two things ,
- If object of that class is created then a virtual pointer (VPTR) is inserted as a data member of the class to point to VTABLE of that class. For each new object created, a new virtual pointer is inserted as a data member of that class.
- Irrespective of object is created or not, class contains as a member a static array of function pointers called VTABLE. Cells of this table store the address of each virtual function contained in that class.
Consider the example below:
//C++ program to demonstrate how a virtual function
// is used in a real life scenario
#include
class Employee {
protected:
int salary ;
public :
virtual void Salary()
{
std::cout <<" Enter employee present salary : " ;
std::cin>>salary ;
}
virtual void raiseSalary( int incrementpercentage)
{
std::cout <<" employee raise salary " ;
}
virtual void printsalary()
{
}
};
class Manager : public Employee
{
public:
void Salary()
{
std::cout <<" manager salary : " ;
std::cin>>salary ;
}
void raiseSalary(int incrementpercentage)
{
// Manager specific raise salary code, may contain
// increment of manager specific incentives
salary = salary*( 1+(0.01*incrementpercentage )) ;
}
void printsalary()
{
std::cout<<" present Manager salary = "<< salary<>salary ;
}
void raiseSalary(int incrementpercentage)
{
// engineer specific raise salary code,
// increment of engineer specific incentives
salary = salary*( 1+(0.01*incrementpercentage )) ;
}
void printsalary()
{
std::cout<<" Present Engineer salary = "<< salary<Salary();
}
int n[4] ;
// for loop for accessing the increase in percentage of salary for each employee
for (int i = 0; i < 4; i++)
{
std::cout<< "Enter percentage of raise in employee :"<< "E[" <<i<< "]" << std::endl;
std::cin>>n[i] ;
}
// for loop for accessing the salary after increasing and print the new salary
for (int i = 0; i < 4; i++)
{
// Polymorphic call to raiseSalary() and printsalary()
// according to the actual object, not
// according to the type of pointer
emp[i]->raiseSalary(n[i]);
emp[i]->printsalary();
}
}
Output :

The compiler maintains two things to serve the virtual functions and run time polymorphism:
- V table : A table of function pointers, maintained per class.
- Vptr : A pointer to vtable, maintained per object instance .
The compiler adds additional code at two places to maintain and use vptr.
1. Code in every constructor. This code sets the vptr of the object being created. This code sets vptr to point to the vtable of the class.
2. Code with polymorphic function call (e.g. emp[i]->raiseSalary(n[i]) , emp[i]->printsalary() in above code). Wherever a polymorphic call is made, the compiler inserts code to first look for vptr using a base class pointer or reference (In the above example, since the pointed or referred object is of a derived type, vptr of a derived class is accessed). Once vptr is fetched, vtable of derived class can be accessed. Using vtable, the address of the derived class function raiseSalary() is accessed and called.
//C++ program to demonstrate how a virtual function
// is used in a real life scenario
#include<iostream>
class Employee {
protected:
int salary ;
public :
virtual void Salary()
{
std::cout <<" Enter employee present salary : " ;
std::cin>>salary ;
}
virtual void raiseSalary( int incrementpercentage)
{
std::cout <<" employee raise salary " ;
}
virtual void printsalary()
{
}
};
class Manager : public Employee
{
public:
void Salary()
{
std::cout <<" manager salary : " ;
std::cin>>salary ;
}
void raiseSalary(int incrementpercentage)
{
// Manager specific raise salary code, may contain
// increment of manager specific incentives
salary = salary*( 1+(0.01*incrementpercentage )) ;
}
void printsalary()
{
std::cout<<" present Manager salary = "<< salary<<std::endl ;
}
} ;
class engineer : public Employee {
public:
void Salary()
{
std::cout <<" Engineer salary : " ;
std::cin>>salary ;
}
void raiseSalary(int incrementpercentage)
{
// engineer specific raise salary code,
// increment of engineer specific incentives
salary = salary*( 1+(0.01*incrementpercentage )) ;
}
void printsalary()
{
std::cout<<" Present Engineer salary = "<< salary<<std::endl ;
}
};
// Similarly, there may be other types of employees
//And also we can create a function called promote in each class to promote employees based on their performance
int main()
{
// We need a very simple algorithm to increment the salary of all employees
// Note that emp[] is an array of pointers and actual pointed objects can be any type of employees.
Employee * emp[4] ;
engineer e1 ,e2 ;
Manager m1 , m2 ;
// assigning derived calsss object to base class pointer to perform run time polymorphism
emp[0] = &e1 ;
emp[1] = &e2 ;
emp[2] = &m1 ;
emp[3] = &m2 ;
// for loop for initializing salaries
for (int i = 0; i < 4; i++)
{
std::cout<< "Enter present salary of employee :"<< "E[" <<i<< "]" << "i.e , " ;
//Polymorphic call to Salary() ,according to the actual object, not according to the type of pointer
emp[i]->Salary();
}
int n[4] ;
// for loop for accessing the increase in percentage of salary for each employee
for (int i = 0; i < 4; i++)
{
std::cout<< "Enter percentage of raise in employee :"<< "E[" <<i<< "]" << std::endl;
std::cin>>n[i] ;
}
// for loop for accessing the salary after increasing and print the new salary
for (int i = 0; i < 4; i++)
{
// Polymorphic call to raiseSalary() and printsalary()
// according to the actual object, not
// according to the type of pointer
emp[i]->raiseSalary(n[i]);
emp[i]->printsalary();
}
}
