Year End Sale: Get Upto 40% OFF on Live Training! Offer Ending in
D
H
M
S
Get Now
Understanding Virtual Functions in C++: A Comprehensive Guide

Understanding Virtual Functions in C++: A Comprehensive Guide

08 Aug 2024
Advanced
4.01K Views
12 min read
Learn with an interactive course and practical hands-on labs

Free C++ Course: Learn C++ In 21 Days

C++ Virtual Functions

C++ Virtual Functions is a technique to implement runtime polymorphism in C++. It's a function declared with the virtual keyword. We have already seen a little about them. 

In this C++ tutorial, we will analyze the workings of a C++ virtual function from all perspectives. So, let's move forward in our learning of OOP concepts in C++. For a complete theoretical and practical understanding, do consider our C++ Certification course.

What is a Virtual Function in C++?

A C++ virtual function is a member function of a parent class declared with a virtual keyword. This function is redefined without the virtual keyword in the derived class to implement the concept of function overriding.

We saw in the C++ Function Overriding tutorial that when a pointer of the base class pointing to the object of the derived class calls the overridden function, the function in the base class gets invoked and not of the derived class. To avoid this, we can define the overridden function in the base class with the virtual keyword. Then using a pointer or a reference to the base class, the derived class object can invoke the derived class’s version of that method.

Are you still facing difficulty in understanding parent classes, derived classes, function calls, and function prototypes? Just refer to the tutorials on Inheritance in C++, functions in C++, Call by Value, and Call by Reference in C++.

Read More - Advanced C++ Interview Interview Questions and Answers

Rules of a Virtual Function

  • Virtual functions cannot be static.
  • They can be a friend of another class.
  • A virtual function must be defined in the base class, even though it is not used.
  • It should be accessed using a pointer or reference of base class type.
  • The virtual function prototype must be the same in the base and the derived class.
  • You can have a virtual destructor in a class but not a virtual constructor.

Example of C++ Virtual Function in C++ Compiler


#include <iosream>
using namespace std;
class DotNetTricks {
public:
 virtual void print() {
 cout << "Welcome to DotNetTricks" << endl;
 }
 void show() {
 cout << "This is the base class" << endl;
 }
};

class ScholarHat : public DotNetTricks {
public:
 void print() {
 cout << "Welcome to ScholarHat" << endl;
 }
 void show() {
 cout << "This is the child/derived class" << endl;
 }
};

int main() {
 ScholarHat sobj1;

 // Pointer of the base class type that points to sobj1
 DotNetTricks* ptr = &sobj1;

 // Virtual function, binded at runtime
 ptr->print();

 // Non-virtual function, binded at compile time
 ptr->show();

 return 0;
}

The above code demonstrates the working of virtual and non-virtual functions.

  • The print() function in the base class, DotNetTricks is declared with a virtual keyword and redefined in the SchoarHat class.
  • The show() function is defined in both classes. It is not declared with a virtual keyword.
  • The pointer ptr of the DotNetTricks class points to the sobj1 object of the ScholarHat class.
  • When we call the print() function through ptr, it calls the overridden print() function in the ScholarHat class because it's virtual and thus binded at runtime.
  • whereas, the same pointer, ptr calls the show() function in the base class because it's not virtual and binded at compile time.

Output

Welcome to ScholarHat
This is the base class

C++ Override Identifier

The override is an identifier introduced in the C++ 11 version. It specifies the member functions of the derived classes that override the member function of the base class. It helps to avoid bugs while using virtual functions.

Example to demonstrate C++ override identifier

class DotNetTricks {
 public:
 virtual void print() {
 // code
 }
};

class Scholarhat : public DotNetTricks {
 public:
 void print() override {
 // code
 }
};

Use of C++ override identifier

When using C++ virtual functions, the following mistakes can be made when declaring the member functions of the derived classes.

  • functions with incorrect names: e.g.if the virtual function in the base class is named print(), but the name in the derived class is pint().
  • functions with different return types: If the virtual function, for example is of void type, but the function in the derived class is of int type.
  • functions with different parameters: If the parameters of the virtual function and the functions in the derived classes don't match.
  • No virtual function is declared in the base class.

The override identifier lets the compiler display error messages when such mistakes are encountered. Otherwise, the program will simply compile but the virtual function will not be overridden.

Pure Virtual Function in C++

It is a do-nothing virtual function declared in the base class with no definition relative to the base class. A base class containing the pure virtual function cannot be used to declare the objects of its own. Such classes are known as abstract base classes.

The main objective of the base class is to provide the traits to the derived classes and to create the base pointer used for achieving the runtime polymorphism in C++.

Syntax

virtual returnType functionName()=0;

Example of pure virtual function in C++


#include <iosream>
using namespace std; 
class DotNetTricks 
{ 
 public: 
 virtual void show() = 0; 
}; 
class ScholarHat : public DotNetTricks
{ 
 public: 
 void show() 
 { 
 cout << "ScholarHat class is derived from the DotNetTricks class." << endl; 
 } 
}; 
int main() 
{ 
 DotNetTricks* ptr; 
 
 ScholarHat sobj1; 
 ptr = &sobj1; 
 ptr->show(); 
 return 0; 
} 

The base class DotNetTricks has a pure virtual function show(). The derived class ScholarHat overrides the show() function. The pointer ptr of the base class calls the show() function.

Output

ScholarHat class is derived from the DotNetTricks class.

Limitations of C++ Virtual Functions

  • Performance Overhead:  Calls to virtual functions are resolved at runtime using a virtual table (vtable), which can slow down execution compared to non-virtual function calls.
  • Memory Overhead: Each class with virtual functions typically includes a vtable, which increases its memory footprint.
  • Constructor and Destructor Calls: Virtual functions cannot be called in constructors or destructors for the currently constructed or destructed object.
  • No Inline Expansion: The compiler typically does not inline virtual functions, even if they are defined within the class body. This can prevent certain optimizations that the compiler might otherwise perform for non-virtual functions.
Summary

We have completed one more polymorphism technique in C++. You need to follow the sequence from the OOPs concepts in C++ to understand everything easily. To practice, enroll in our C++ Certification program.

Share Article
About Author
Shailendra Chauhan (Microsoft MVP, Founder & CEO at ScholarHat)

Shailendra Chauhan, Founder and CEO of ScholarHat by DotNetTricks, is a renowned expert in System Design, Software Architecture, Azure Cloud, .NET, Angular, React, Node.js, Microservices, DevOps, and Cross-Platform Mobile App Development. His skill set extends into emerging fields like Data Science, Python, Azure AI/ML, and Generative AI, making him a well-rounded expert who bridges traditional development frameworks with cutting-edge advancements. Recognized as a Microsoft Most Valuable Professional (MVP) for an impressive 9 consecutive years (2016–2024), he has consistently demonstrated excellence in delivering impactful solutions and inspiring learners.

Shailendra’s unique, hands-on training programs and bestselling books have empowered thousands of professionals to excel in their careers and crack tough interviews. A visionary leader, he continues to revolutionize technology education with his innovative approach.
Accept cookies & close this