Understanding the “virtual” in C++

Understanding the "virtual" in C++

What is the “virtual” keyword in C++?

A virtual function, also known as a virtual method, is a special kind of function that is used in classes. It’s like a blueprint in the main class that can be changed or customized in the child classes. When you have a main class and make a similar function in the child class, it replaces the main one. This is useful when you want to use the same function but with slightly different behaviors in different situations.

Imagine you have a base class that defines a function, and then you make different versions of that function in subclasses. When you use a reference or pointer of the main class to call the function, it actually calls the version of the function in the subclass, not the one in the main class. This makes sure that you get the behavior specific to the subclass even when you’re using the main class reference.

Virtual functions are like a way of telling the computer “Hey, there might be different versions of this function, so use the right one based on the actual object.” This is really helpful when you want to achieve different behaviors in different situations. It’s like a cool trick in programming that lets you decide what a function does not when you write the code, but when you run it.

Rules for Virtual Functions

  • Virtual functions are used to achieve runtime polymorphism in inheritance.
  • The base class function should be declared as virtual, and the derived class function should also be declared as virtual if you intend to override it.
  • Virtual functions must have the same name and parameters in both base and derived classes.
  • Constructors and destructors cannot be declared as virtual.
  • Virtual functions are resolved at runtime based on the actual object type, using the vtable mechanism.
  • If a derived class overrides a virtual function, the function in the derived class will be called even if accessed through a base class pointer or reference.
  • You can’t define a virtual function with the ‘inline’ specifier.
  • The return type of a virtual function can be covariant, meaning it can be a pointer or reference to a derived class when overridden in the derived class.
  • If a base class declares a virtual function, it’s recommended to provide a default implementation to avoid pure virtual functions (abstract base classes).

Compile time (early binding) VS runtime (late binding) behavior of Virtual Functions

Here’s an example that demonstrates the compile-time (early binding) and runtime (late binding) behavior of virtual functions in C++:

C++
#include <iostream>
using namespace std;

class Base {
public:
    virtual void show() {
        cout << "Base class function" << endl;
    }
};

class Derived : public Base {
public:
    void show() override {
        cout << "Derived class function" << endl;
    }
};

int main() {
    Base *basePtr;
    Derived derivedObj;

    basePtr = &derivedObj;  // Pointing to the derived object

    // Early Binding - Compile-time
    basePtr->show();  // Calls the Base class show()

    // Late Binding - Runtime
    derivedObj.show();  // Calls the Derived class show()

    return 0;
}

Output:

C++
Base class function
Derived class function

In this example, we have a base class ‘Base‘ and a derived class ‘Derived‘ that inherits from the base class. Both classes have a virtual function ‘show()‘. In the ‘main()‘ function, we create a pointer of the base class type and point it to an object of the derived class. When we call the ‘show()‘ function using the pointer, the behavior depends on whether it’s compile-time or runtime:

  1. Compile-time (Early Binding): When we call ‘basePtr->show()‘, the compiler uses the type of the pointer to determine which function to call. Since the pointer is of type ‘Base*‘, the ‘Base‘ class ‘show()‘ function is called.
  2. Runtime (Late Binding): When we call ‘derivedObj.show()‘, the function called depends on the actual object type. Since ‘derivedObj‘ is of type ‘Derived‘, the ‘Derived‘ class ‘show()‘ function is called.

Working on Virtual Functions (concept of VTABLE and VPTR) in C++

Code Example:

C++
#include <iostream>
using namespace std;

class Shape {
public:
    virtual void draw() {
        cout << "Drawing a Shape." << endl;
    }
};

class Circle : public Shape {
public:
    void draw() {
        cout << "Drawing a Circle." << endl;
    }
};

class Triangle : public Shape {
public:
    void draw() {
        cout << "Drawing a Triangle." << endl;
    }
};

int main() {
    Shape* shape1 = new Circle();
    Shape* shape2 = new Triangle();

    shape1->draw();
    shape2->draw();

    delete shape1;
    delete shape2;

    return 0;
}

Output:

C++
Drawing a Circle.
Drawing a Triangle.

Explanation:

  • The example includes a base class named Shape with a virtual function ‘draw()‘.
  • Two derived classes, ‘Circle‘ and ‘Triangle‘, override the ‘draw()‘ function in their own way.
  • Instances of the derived classes are created.
  • The ‘draw()‘ function is called using pointers of the base class.
  • The appropriate derived class version of the function is executed.
  • This behavior is achieved through VTABLE and VPTR concepts.
  • VTABLE and VPTR help the program determine the correct function to call based on the actual object type pointed to by the pointer.

Why do we need the “virtual” keyword in C++?

In C++, the “virtual” keyword is used to indicate that a function in a base class can be overridden by a function with the same name in its derived classes. When we use “virtual,” it tells the compiler that this function might be redefined in a derived class, and the actual function to be executed will be determined at runtime based on the object’s type.

This is important because it allows us to achieve polymorphism, which means that even when we have a pointer to a base class object that is actually pointing to a derived class object, the correct version of the function in the derived class will be called. This helps in achieving flexibility and dynamic behavior in object-oriented programming. Without the “virtual” keyword, the base class’s function would be called regardless of the actual object’s type, and we would lose the ability to create specialized behaviors in derived classes.

Real-life Example

Imagine the “virtual” keyword as a special power in a video game. Like how each character in the game can perform a similar action but with a unique style, the “virtual” keyword lets us create different versions of a function for different classes. It’s like giving the function a superpower that adapts based on the class using it. So, with “virtual,” we can have similar functions in various classes, each tailored to their specific needs. It’s a fantastic tool for making our code more flexible and dynamic, just like a fun video game!

A Problem to Solve

Problem Statement: Zoo Animals and Their Sounds

You are tasked with modeling a simple zoo system where animals can make sounds. However, not all animals make the same sound. For example, a tiger roars, while a bird chirps.

Using the concept of inheritance and polymorphism in C++, create a base class ‘Animal‘ that has a virtual function named ‘makeSound()‘. This function should return the sound the animal makes as a string.

Now, derive at least three subclasses: ‘Tiger‘, ‘Bird‘, and ‘Snake‘. Override the ‘makeSound()‘ function in each of these derived classes to return a sound specific to that animal.

Finally, write a main function where you create pointers of type ‘Animal‘ pointing to objects of the derived classes. Demonstrate polymorphism by calling the ‘makeSound()‘ function using these pointers and displaying the sound for each animal.

Requirements:

  1. Use a base class ‘Animal‘ with a virtual function named makeSound().
  2. Derive subclasses ‘Tiger‘, ‘Bird‘, and ‘Snake‘ from the ‘Animal‘ class.
  3. Override the ‘makeSound()‘ function in each subclass.
  4. In the main function, demonstrate polymorphism using pointers.

Hints:

  1. Remember the syntax to declare a virtual function: ‘virtual ReturnType FunctionName()‘.
  2. Overriding is done by redefining the base class function in the derived class with the same function signature.
  3. Use pointers of the base class type to point to derived class objects to demonstrate polymorphism.

Expected Output:

C++
Tiger: Roar!
Bird: Chirp!
Snake: Hiss!

The Pros and Cons of Using the “virtual” keyword

Pros of using “virtual”Cons of using “virtual”
Allows polymorphism, which means we can treat objects of different classes as the same type and call the correct function dynamically based on the object’s actual type.Slightly slower performance compared to non-virtual functions due to the overhead of dynamic dispatch.
Enables flexibility in designing class hierarchies and supporting various implementations for the same function in different derived classes.Increases complexity in code, especially for large projects, as it requires careful planning and understanding of inheritance and virtual functions.
Facilitates extensibility, as new classes can be easily added with their specific implementations of virtual functions.Might lead to confusion and potential errors if the “virtual” keyword is used incorrectly or excessively without proper design considerations.
Encourages code reuse and modular design by allowing shared functionality to be defined in a base class and overridden in derived classes as needed.Requires an additional memory overhead for the virtual function table (vtable) when objects of the class with virtual functions are created.
The Pros and Cons of Using the “virtual” keyword

Key Takeaways

The “virtual” keyword in C++ is a powerful tool that allows us to create different implementations of a function for different classes. By understanding how to use the “virtual” keyword, you can make your programs more flexible and extensible.

Conclusion

In conclusion, the “virtual” keyword is a fundamental part of C++. It allows us to use the polymorphism feature in C++, which is a key aspect of object-oriented programming. So keep practicing, and soon you’ll be a pro at using the “virtual” keyword!

FAQs

  • What is the “virtual” keyword in C++?
    • The “virtual” keyword in C++ is used in the declaration of a function to tell the compiler that the function can be overridden in a derived class.
  • Why do we use the “virtual” keyword in C++?
    • We use the “virtual” keyword in C++ to create different implementations of a function for different classes. It allows us to use the polymorphism feature in C++, which is a key aspect of object-oriented programming.
  • How do we use the “virtual” keyword in C++?
    • We use the “virtual” keyword in the declaration of a function in the base class. When we create a derived class, we can override this function to provide a different implementation.
  • Can using the “virtual” keyword makes code more confusing?
    • Yes, if you use the “virtual” keyword without a proper understanding, it can make your code more complex and harder to understand. It’s important to understand how the “virtual” keyword works and when to use it.
  • What are some examples of using the “virtual” keyword in C++?
    • Some examples include creating different characters in a video game with unique abilities, creating a simulation program for a zoo where different animals make different sounds, and creating different shapes in a drawing program.
Deepak Vishwakarma

Founder

RELATED Articles

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.