Project

Classes and Objects

1) Operator overloading to perform sum of two complex numbers :
 #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 ,

  1. 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.
  2. 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();

    }
}

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.