22
DecUnderstanding Virtual Functions in C++: A Comprehensive Guide
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 avirtual
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 avirtual
keyword and redefined in theSchoarHat
class. - The
show()
function is defined in both classes. It is not declared with a virtual keyword. - The pointer
ptr
of theDotNetTricks
class points to thesobj1
object of theScholarHat
class. - When we call the
print()
function throughptr
, it calls the overriddenprint()
function in theScholarHat
class because it'svirtual
and thus binded at runtime. - whereas, the same pointer,
ptr
calls theshow()
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 ispint()
. - functions with different return types: If the virtual function, for example is of
void
type, but the function in the derived class is ofint
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.