virtual_function


Concept: virtual function

A virtual function in C++ is a member function in a base class that you expect to be overridden in derived classes. When a function is declared as virtual, C++ uses a mechanism known as dynamic dispatch or runtime polymorphism to determine which function to call, based on the actual type of the object pointed to, rather than the type of the pointer or reference. This is a key concept in object-oriented programming, allowing for more flexible and reusable code.

Key Characteristics of Virtual Functions

Example 1: Basic Use of Virtual Functions

Here's a simple example demonstrating how virtual functions work in C++:

#include <iostream>

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

class Derived : public Base {
public:
    void show() override {  // Override the base class function
        std::cout << "Derived class show() function called." << std::endl;
    }
};

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

    basePtr = &derivedObj;

    // This will call the derived class's show() method
    basePtr->show();

    return 0;
}

Explanation:

Example 2: Pure Virtual Functions and Abstract Classes

A pure virtual function is a virtual function that has no implementation in the base class and must be overridden in any derived class. A class containing at least one pure virtual function is known as an abstract class and cannot be instantiated.

#include <iostream>

class Shape {
public:
    virtual void draw() = 0;  // Pure virtual function
};

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

class Square : public Shape {
public:
    void draw() override {
        std::cout << "Drawing Square." << std::endl;
    }
};

int main() {
    Shape* shape;

    Circle circle;
    Square square;

    shape = &circle;
    shape->draw();  // Calls Circle's draw()

    shape = &square;
    shape->draw();  // Calls Square's draw()

    return 0;
}

Explanation:

Example 3: Virtual Destructors

When dealing with inheritance, especially with virtual functions, it's crucial to define a virtual destructor in the base class. This ensures that the destructor for derived classes is called correctly when an object is deleted through a base class pointer.

#include <iostream>

class Base {
public:
    Base() {
        std::cout << "Base constructor called." << std::endl;
    }
    virtual ~Base() {  // Virtual destructor
        std::cout << "Base destructor called." << std::endl;
    }
};

class Derived : public Base {
public:
    Derived() {
        std::cout << "Derived constructor called." << std::endl;
    }
    ~Derived() {
        std::cout << "Derived destructor called." << std::endl;
    }
};

int main() {
    Base* basePtr = new Derived();
    delete basePtr;  // Correctly calls Derived's destructor followed by Base's destructor

    return 0;
}

Explanation:

Example 4: Virtual Function Overriding in Multiple Inheritance

When dealing with multiple inheritance, C++ resolves virtual functions correctly by looking at the most derived class.

#include <iostream>

class A {
public:
    virtual void show() {
        std::cout << "A's show() called." << std::endl;
    }
};

class B : public A {
public:
    void show() override {
        std::cout << "B's show() called." << std::endl;
    }
};

class C : public B {
public:
    void show() override {
        std::cout << "C's show() called." << std::endl;
    }
};

int main() {
    A* ptr = new C();
    ptr->show();  // Calls C's show()
    delete ptr;

    return 0;
}

Explanation:

Summary

Understanding virtual functions is fundamental to mastering object-oriented programming in C++. They enable polymorphism, one of the key principles of OOP, allowing you to write more flexible and reusable code.

Previous Page | Course Schedule | Course Content