×

Virtual Functions and Runtime Polymorphism in C++

In this tutorial, we will explore more on virtual functions and runtime polymorphism in the most useful language C++.

A virtual function is a member function with the keyword virtual used in its declaration in the base class and redefined (Overridden) in the derived class. It instructs the compiler to conduct late binding, in which the compiler performs the function during runtime after matching the object with the appropriately called function. Runtime Polymorphism applies to this method.

The word "polymorphism" refers to the capacity to assume various forms. It happens when classes are arranged in a hierarchy and are all related to one another through inheritance. When we deconstruct polymorphism into "Poly - Many" and "morphism - Forms," it simply means displaying different traits in various contexts.

Virtual Functions and Runtime Polymorphism in C++

Keep in mind: Calling a virtual function in C++ refers to the fact that depending on the kind of object that called the function, a different function can be executed in its place.

The virtual call technique is forbidden in constructors since overriding from derived classes hasn't happened yet. Objects are constructed from the ground up or using a bottom-to-top methodology, it should be added.

Take the simple program that follows as an illustration of runtime polymorphism. The function of the derived class is called using a base class pointer, which is the most crucial aspect of the program to remember.

Virtual functions are supposed to be called based on the type of the object instance being pointed to or referenced, not the type of the pointer or reference.

In other words, runtime is when virtual function resolution occurs. In C++, a virtual function is used to choose the member function of a class at runtime. The identically named function in the derived class replaces the base class function.

Virtual function in C++: Syntax

Virtual functions are defined using the term virtual.

Class ClassName
 {
   public:
     virtual return FuncionName ( args. )
      {
        // Function definition
      }
 }

To help one comprehend, we'll now look at an example without using virtual function notions.

C++ Program:

// Using a C++ program, we can illustrate how to calculate the area of shapes without using virtual functions.
#include <iostream>
using namespace std;


// Base class
class Shape1 {
public:
	// constructed with parameters
	Shape1 ( int len, int wid )
	{
		length = len;
		width = wid;
	}
	int getArea ()
	{
		cout << "The parent class area is being called.\n";
		// When a user-defined function returns 1, it means "true."
		return 1;
	}


protected:
	int length, width;
};


// Derived class
class Square1 : public Shape1 {
public:
	Square1 ( int len = 0, int wid = 0 )
		: Shape1 ( len, wid )
	{
	} // Considering derived class constructor
	int getArea ()
	{
		cout << "Square area: " << length * width << '\n';
		return ( length * width );
	}
};
// Derived class
class Rectangle1 : public Shape1 {
public:
	Rectangle1 ( int len = 0, int wid = 0 )
		: Shape1 ( len, wid )
	{
	} // Considering derived class constructor
	int getArea ()
	{
		cout << "Rectangle area: " << length * width
			<< '\n';
		return ( length * width );
	}
};


int main ()
{
	Shape1* sp;


	// Making a square1 object for the child class
	Square1 sqr (5, 5);


	// Making a rectangle1 object for the child class
	Rectangle1 rect ( 4, 5 );
	sp = &sqr; // reference variable
	sp -> getArea ();
	sp  = &rect; // reference variable
	sp -> getArea ();


	return 0; // to verify that the code perform successfully.
}

Output:

The parent class area is being called.
The parent class area is being called.

In the Aforementioned Illustration:

It should have called the corresponding getArea() functions of the child classes, but instead, it calls the getArea() function specified in the base class. We save the address of each child class's Rectangle1 and Square1 object in sp, and then we call the getArea() function on it. This occurs as a result of static linkage, which means the compiler only sets the call to getArea() once, in the base class.

Example: A C++ programme that uses virtual functions to calculate the area of shapes

C++ Program:

// Using a virtual function, a C++ program will show users how to calculate the area of shapes.
#include <fstream>
#include <iostream>
using namespace std;


// Declaring Base class
class Shape1 {
public:
	// Using virtual constructor
	virtual void calculating ()
	{
		cout << "Area of your Shape ";
	}
	// preventing memory leaks by utilising a virtual destructor
	virtual ~Shape1 ()
	{
		cout << "Shape Destuctor Call\n";
	}
};


// Declaring Derived class
class Rectangle1 : public Shape1 {
public:
	int w, h, A;


	void calculating ()
	{
		cout << "Put Width of Rectangle in: ";
		cin >> w;


		cout << "Put Height of Rectangle in:";
		cin >> h;


		A = h * w;
		cout << "Area of Rectangle: " << A << "\n";
	}


	// A virtual destructor for each derived class
	virtual ~Rectangle1 ()
	{
		cout << "Rectangle Destuctor Call\n";
	}
};


// Declaring 2nd derived class
class Square1 : public Shape1 {
public:
	int s, A;


	void calculating ()
	{
		cout << "Put one side your of Square: ";
		cin >> s;


		A = s * s;
		cout << "Area of Square: " << A << "\n";
	}


// A virtual destructor for each derived class
	virtual ~Square1 ()
	{
		cout << "Square Destuctor Call\n";
	}
};


int main ()
{


	// base class pointer
	Shape1* Sp;
	Rectangle1 rect;


	// initializing of reference variable
	Sp = &rect;


	// calling Rectangle function
	Sp -> calculating ();
	Square1 sqr;


	// initializing of reference variable
	Sp = &sqr;


	// calling Square function
	Sp -> calculating ();


	// to verify that the code perform successfully
	return 0;
}

Output: (If the user puts 3, 12, 4 as three consecutive inputs)

Put Width of Rectangle in: 3
Put Height of Rectangle in:12
Area of Rectangle: 36
Put one side your of Square: 4
Area of Square: 16
Square Destuctor Call
Shape Destuctor Call
Rectangle Destuctor Call
Shape Destuctor Call

What is the goal?

  • Without even being aware of the type of derived class object, virtual functions enable us to compile a list of base class pointers and call any of the derived classes' methods.
  • Examples from Real Life to Help one Understand How Virtual Functions Are Implemented
  • Think about a company's employee management software.
  • Create a straightforward basic class called Employee in the code, then add virtual methods to it like raisesalary(), transfer(), and promotion().
  • The virtual functions that are included in the base class Employee may have different implementations for different employee kinds like Executives, Engineers, etc.
  • Without even understanding the type of employee, we just need to pass a list of employees anywhere in our full software and call the necessary functions.
  • For instance, by going through the list of employees repeatedly, we may quickly increase the salaries of all the employees.
  • We don't need to worry about the internal logic that each employee type may have because only that function would be run if raisesalary() was present for that employee type.

C++ Program:

// A virtual function's utility in a real-world context is demonstrated through a C++ program.
class Employee {
public:
	virtual void raise_salary()
	{
		// code of common raise salary 
	}


	virtual void promotion ()
	{
		// code of common promote 
	}
};


class Manager : public Employee {
	virtual void raise_salary ()
	{
		// Code for manager-specific salary increases that may also include an increase in manager-specific incentives
	}


	virtual void promotion ()
	{
		// Manager specific promotion
	}
};


// Likewise, there might be different kinds of workers.


/* To increase the salaries of all employees, we require a fairly straightforward function.
Empl[] is an array of pointers, and the actual pointed objects might be any kind of employees.
We made this function global to keep things simple even though it should ideally be in a class like Organization.*/


void globalRaiseSalary ( Employee* Empl [], int num )
{
	for ( int i = 0; i < num; i++ ) {
		// Polymorphic Call: Calls raise_salary()
		// according to the actual object, not
		// according to the type of pointer
		Empl [i] -> raise_salary();
	}
}
  • Many more operations on a list of employees can be carried out similarly to the 'globalRaiseSalary()' function even without understanding the type of the object instance.
  • Modern programming languages, like Java, maintain all methods virtual by default since virtual functions are so helpful.
  • What sort of runtime resolution does the compiler do?
  • To accomplish this, the compiler keeps two things in order:
  • vtable: A list of function pointers that is updated for each class.
  • vptr: An object instance-specific pointer to the vtable.
  • To use and maintain vptr, the compiler writes extra code twice.

1. Include code in all constructors. The vptr of the object being formed is set by this code. This code causes vptr to point to the class's vtable.

2. Code that calls polymorphic functions, such as bp->show() in the code above. Every time a polymorphic call is made, the compiler adds code to first check 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). Access to the derived class vtable is possible after retrieving the vptr. The address of the display() derived class method is obtained and invoked using vtable.

Is this the accepted practise for C++ run-time polymorphism implementation?

Although the C++ standards do not specify the specific implementation of runtime polymorphism, most compilers employ slight variations of the same fundamental model.


Related Topics

How to calculate size of string in C++

What is string in C++? In C++, a string is a sequence of characters. The string data type is part of the Standard Template Library (STL) and is defined in the...

4 minutes read.

C++ Tricks for Competitive Programming

If you are interested in Computer science or Information technology, you must have heard about competitive programming. Competitive programming is a way to improve your problem-solving skills. There are various...

7 minutes read.

C++ find missing in the second array

Given two arrays A and B of sizes n and m. Find the elements from array A that are not present in array B. Example Input : a[] = {1, 2, 3, 5,...

3 minutes read.

Input Iterators in C++

What are input iterators? Input iterators are used in sequence for carrying out input operations where each value is read-only. It is pointed by the iterator and further incremented. All the iterators...

4 minutes read.

Top 14 Best Free C++ IDE (Editor & Compiler) for Windows in 2024

Bjarne Stroustrup created the all-purpose object-oriented programming language C++. To develop C++ programs, there are various Integrated Development Environments (IDE) that offer prewritten code templates. These programs automatically modify the...

6 minutes read.

Single dimension array

C++ Array An array is a collection of data (elements) of the same data types. The elements of an array are allocated in contiguous memory allocation. Elements of the array are accessed through...

1 minute read.

swap() function in C++

Swap() function: swap() function in C++: swap() function is a pre-define function in c++ present in STL( Standard template library ). It is used to swap two numbers. It takes two mandatory...

6 minutes read.

C++ Reading file

In file handling, read() function is used to read data from the file into the program. The read() uses ifstream library to read data from a file. Syntax file-stream-class   file-stream-object;   file-stream-object.read((char *)&var , sizeof (var)); <h3">Example ofstream  outfile;         outfile . read((char*)&emp,sizeof(emp)); C++ File Handling read() Function Example Reading the content of existing...

2 minutes read.

How to create a stack in C++

A stack is a data structure, which is of linear type. A specific order has to be followed while inserting and deleting the elements from the stack. Generally, stack follows...

5 minutes read.

Loops in C++

A loop statement in most programming languages allows us to execute a statement or a collection of statements numerous times. Control structures of programming languages vary, allowing for more complex...

6 minutes read.

C++ Socket Programming

In this world, computer networking has become very important for sharing of data. Every good programmer has some knowledge about computer networking. Socket programming is one of the critical topics...

6 minutes read.

Learn C++ Tutorial

C++ Introduction C++ is an object-oriented programming language. It was developed by Bjarne Stroustrup at AT&T Bell Laboratories. It is superset (extension) of C programming language. Depending upon features supported by programming...

10 minutes read.

Compile Time Polymorphism in C++

What is Polymorphism? Polymorphism refers to the existence of various forms. Polymorphism can be simply defined as a message's capacity to be presented in multiple forms. One application of polymorphism in...

4 minutes read.

4-Dimensional Array in C/C++

A four-dimensional (4D) array is an array of three-dimensional (3D) arrays, or in other words we can say that a 4- dimensional array is an array of arrays of arrays...

3 minutes read.

How to make a password program in C++

Before understanding the password program, one must know about a password and why it is required. Password: A password is a word that permits access to somewhere or something. A password...

4 minutes read.

Initialize Array of objects with parameterized constructors in C++

Initialize Array of objects with parameterized constructors in C++ When a class is defined, only the specification for the object is specified; no memory or capacity is allocated. You need to...

3 minutes read.

How to build a program in C++

Building a program is all about creating the program and executing it successfully. There are some steps  precisely, which must be followed to make the program. Step 1: Get an IDE...

4 minutes read.

Reverse function in C++

The function std::reverse() is included in the standard template library of C++. It takes in a beginning and ending iterator, reversing the order. To use the reverse statement, we need...

2 minutes read.

C++ int into String

Data type conversion is a standard editing process. You may need to convert variable from one type of data to another in a variety of situations. There are two ways...

5 minutes read.

Binary Operator Overloading in C++

The Binary Operator Overloading in the C++ programming language will be covered in this part. An operator which comprises two operands to execute a mathematical operation is termed the Binary...

6 minutes read.