Virtual Functions In C++ - C++ Programming Tutorial
C++ Course / Polymorphism / Virtual Functions In C++

Virtual Functions In C++

BLUF: Mastering Virtual Functions In C++ is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: Virtual Functions In C++

C++ is renowned for its efficiency. Learn how Virtual Functions In C++ enables low-level control and high-performance computing in the tutorial below.

In C++, a virtual method is a function within a class that can be redefined in a subclass. It is specified in the superclass and can be customized in a subclass by using the virtual keyword.

When a function is defined in the parent class, we can employ a pointer and reference to call the virtual function in the child class, thereby triggering its virtual behavior. This is commonly referred to as the virtual method.

A virtual method is employed to instruct the compiler to implement late binding or dynamic linkage on the method. This facilitates runtime polymorphism, enabling the dynamic resolution of function calls through virtual tables (vtables) and v-pointers (vptrs).

Syntax

It has the following syntax:

Example

class baseClass_name {

public:

	Virtual void funct_name() {

	//code implementation

	}

};

In this structure, the baseClassname denotes the title of the base class, while the functname signifies the title of the specified function.

C++ Virtual Function Example

Let's consider an example to illustrate the concept of virtual functions in C++.

Example

Example

#include <iostream>

using namespace std; //using standard namespace

class baseClass {

public: //Access Modifier

    virtual void display() //declaring Virtual function

    { 

        cout << "It is the print base class method\n"; 

        

    }

    void show() 

    { 

        cout << "It is the show base class method\n"; 

        

    }

};

class derived : public baseClass {

public:

    void display() 

    { 

        cout << "It is the print derived class method\n"; 

        

    }

    void show() 

    {

        cout << "It is the show derived class method\n"; 

        

    }

};

int main() //Main Function

{

    baseClass* bptr;

    derived d1;

    bptr = &d1;

    // The Virtual function at the runtime

    bptr->display();

    // Non-virtual function at the compile time

    bptr->show();

    return 0;

}

Output:

Output

It is the print derived class method

It is the show base class method

Explanation

In this illustration, we are considering a baseClass that includes a virtual method print and a non-virtual method show. Within the main function, a baseClass pointer (bptr) is assigned to reference an object of the derived class type (d1). Upon executing bptr->display, the late binding mechanism occurs, resulting in the invocation of the overridden function within the derived class.

Rules of Virtual Function

Several rules of virtual function in C++ are as follows:

  • Virtual functions must be members of some class.
  • Virtual functions cannot be static members. They can be accessed via objeccpp tutorialers.
  • In the base class, a virtual function can have any access level (including public, private, and protected).
  • The virtual functions can be a friend of another class.
  • They can have any return type, number, and argument type.
  • A virtual function should be defined in the base class, even though it is not used in the program.
  • The prototypes of a virtual function of the base class and all the derived classes should be the same. If the two functions with the same name but different prototypes, C++ will consider them as overloaded functions.
  • We cannot have a virtual constructor, but we can have a virtual destructor.
  • Virtual Table (vTable) and Virtual Pointer (vPtr)

In C++, the virtual table (vTable) serves as a concealed mechanism primarily employed for executing runtime polymorphism through virtual functions. Within a virtual function, each class is associated with a distinct vTable, and every instance of that class contains an undisclosed vPtr linking to the vTable. This vTable stores the memory addresses of virtual functions that are accessible for invocation on instances of the respective class.

On the flip side, the virtual pointer is an internal pointer present in each object of a class containing virtual functions. It is integrated by the compiler as part of the member functions. Its purpose is to reference the vTable specific to that class. When a virtual function is invoked in the code, the VPTR plays a crucial role in locating the accurate function address within the VTable dynamically.

C++ vTable and vPtr Example

Let's consider an example to demonstrate the vTable and vPtr in C++.

Example

Example

#include <iostream>

using namespace std;  //using standard namespace

class Car { // Base class

public:

    virtual void start() {  // Virtual function

        cout << "Car is starting..." << endl;

    }

};

class RacingCar : public Car {  // Derived class

public:

    void start() override {  // Overriding virtual function

        cout << "RacingCar is starting with a loud roar!" << endl;

    }

};

int main() //Main Function

{

    Car* carPtr;   //It is the base class pointer

    RacingCar rc;  //It is the derived class object

    carPtr = &rc;  //points base class pointer to derived class object

    carPtr->start();  // Late binding occurs via vTable and vPtr

    return 0;

}

Output:

Output

RacingCar is starting with a loud roar!

Explanation

In this instance, we are working with a foundational class Car that contains a virtual method start, which is redefined in the subclass RacingCar. Within the main function, a pointer carPtr of the base class is directed towards an instance of RacingCar.

When calling carPtr->start, dynamic binding takes place utilizing the vTable and vPtr, leading to the execution of the start method from the RacingCar class during runtime.

Late Binding/Dynamic Binding in C++

In C++, dynamic binding is the process in which the function invocation is determined at runtime. This occurs specifically when a virtual function is invoked through a pointer or reference to the base class. Consequently, the compiler identifies the object type during program execution and subsequently links the function call accordingly.

When a virtual method is called on an instance through a pointer or reference to the base class, we can rely on the virtual function table (vtable) associated with the specific instance during runtime. This mechanism enables the execution of the appropriate subclass method.

C++ Late Binding Example

Let's consider a scenario to demonstrate Late Binding in C++.

Example

Example

#include <iostream>

using namespace std; //Using Standard Namespace

class Animal {  //class

public:

    virtual void display() {  // base class

        cout << "Animal color black\n";

    }

};

class Dog : public Animal {

public:

    void display() override {  // derived class

        cout << "Dog color gray\n"; 

    }

};

int main() {

    Animal* ptr;

    Dog d;

    ptr = &d;

    ptr->display();  //Late Binding

    return 0;

}

Output:

Output

Dog color gray

Explanation

In this instance, we've utilized a foundational class, Animal, which specifies a virtual method display. Following this, the subclass Dog redefines the virtual method. The ptr ->display invocation triggers dynamic binding, executing the display method from the Dog class since the object type is Dog.

Pure Virtual Function in C++

In C++, the abstract method is a pure virtual function without an implementation. This type of function is often referred to as a "do-nothing" function because it lacks a definition in the base class where it is declared.

A class that includes a pure virtual function cannot be directly instantiated. Such classes are referred to as abstract base classes. The primary purpose of the base class is to impart characteristics to derived classes and to establish the base pointer required for implementing runtime polymorphism.

Syntax

It has the following syntax

Example

class Class_Name {

public:

    virtual function_type function_name() = 0;  // Pure Virtual Function

};

C++ Pure Virtual Function Example

Let's consider an example to demonstrate the concept of an abstract virtual function in the C++ programming language.

Example

Example

#include <iostream>  

using namespace std;  //using standard namespace

class Base  //Abstract base class

{  

    public:  //Access modifier

    virtual void show() = 0;   //Pure Virtual function

};  

class Derived : public Base  

{  

    public:  

    void show()  

    {  

        std::cout << "Derived class is derived from the base class." << std::endl;  

    }  

};  

int main()  //Main Function

{  

    Base *bptr;  //base class pointer

    //Base b;  

    Derived d;  

    bptr = &d;  

    bptr->show();  

    return 0;  

}

Output:

Output

Derived class is derived from the base class.

Explanation

In this instance, the base class includes the abstract function. Consequently, the base class is classified as an abstract base class, making it impossible to instantiate objects from it.

Advantages and Disadvantages of Virtual Functions in C++

Several benefits and drawbacks of virtual functions in C++ are outlined below:

Advantages of Virtual Functions

  • It enables the derivation function in the derived class, which allows method overriding.
  • It allows the design of user-friendly applications with minimal restrictions on the introduction of new derived classes, i.e. existing base class code does not require alteration.
  • It increases the flexibility in the execution of a program as the calling of a function is done during program execution instead of during the writing of code.
  • It ensures full functionality of the derived class when it is stored in the base class pointer for virtual function cases.
  • It is useful in GUI frameworks, game engines, and plugin-based architectures.
  • Disadvantages of Virtual Functions

  • The function call takes a long time because of the virtual mechanism, which makes it more complex for compilers to optimize because it does not know which function will be called.
  • In a complex system, the virtual function can make it more difficult to find where a function has been called.
  • Virtual functions can cause several problems with some optimization techniques, which reduces performance.
  • In virtual function, every class contains a virtual table (vtable) that increases its main memory.
  • C++ Virtual Function MCQs

1) Which of the following classes is used to redefine a virtual function in C++?

  • Parent class
  • Base class
  • Derived class
  • All of the above

2) In C++ late/dynamic binding, the function call is resolved during?

  • Compile Time
  • Runtime
  • Infinite Time
  • None of the above

The program's output will be dependent on the specific code being referenced, as the provided question lacks the necessary context or code snippet for analysis.

Example

#include <iostream>

using namespace std;

class Car {

public:

    virtual void display()

    {

        cout << "This is a car.";

    }

};

class Speedcar : public Car {

public:

    virtual void display()

    {

        cout << "This is a speed car.";

    }

};

int main()

{

    Speedcar sc;

    sc.display();

    return 0;

}
  • This is a speed car.
  • This is a car
  • Runtime Error
  • Syntax Error

4) Which of the following options is used to access virtual functions in C++?

  • Array
  • Variable
  • Objeccpp tutorialers
  • Object

5) What is the correct syntax of Pure Virtual Function in C++?

  • pure virtual return_type func;
  • virtual return_type func = 0;
  • virtual return_type func;
  • virtual return_type func pure;

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience