ScholarQuill logoScholarQuillUniversity Notes
  • Notes
  • Past Papers
  • Blogs
  • Todo
Login
ScholarQuill logoScholarQuillUniversity Notes
Login
NotesPast PapersBlogsTodo
More
SubjectsDiscussionCGPA CalculatorGPA CalculatorStudent PortalCourse Outline
About
About usPrivacy PolicyReportContact
Notes
Past Papers
Blogs
Todo
Analytics
    Current Subject
    🧩
    Object Oriented Programming
    CSI-312
    Progress0 / 16 topics
    Topics
    1. Evolution of Object-Oriented (OO) Programming2. Object-Oriented (OO) Concepts and Principles3. Problem Solving in OO Paradigm4. OO Programme Design Process5. Classes6. Methods7. Objects and Encapsulation8. Constructors and Destructors9. Operator Overloading10. Function Overloading11. Virtual Functions12. Derived Classes13. Inheritance14. Polymorphism15. I/O and File Processing16. Exception Handling
    CSI-312›Virtual Functions
    Object Oriented ProgrammingTopic 11 of 16

    Virtual Functions

    8 minread
    1,302words
    Intermediatelevel

    Virtual Functions in C++

    A virtual function in C++ is a function that is defined in a base class and is meant to be overridden by derived classes. It is used to achieve runtime polymorphism, where the function call is resolved at runtime rather than compile-time. Virtual functions allow for dynamic dispatch, meaning that the correct function (the one corresponding to the actual object type, not the pointer type) is called at runtime.

    Key Concepts of Virtual Functions

    1. Runtime Polymorphism: Virtual functions enable runtime polymorphism, where the method that is called is determined at runtime based on the type of the object being referred to by the pointer or reference.

    2. Overriding: A virtual function in a base class can be overridden by a function in a derived class. When a virtual function is overridden, the derived class function is called instead of the base class function.

    3. Virtual Keyword: The virtual keyword is used in the base class to declare a function as virtual. The keyword ensures that the derived class method (if overridden) is called when invoked through a base class pointer or reference.

    4. Base Class Pointers and References: Virtual functions work when they are called through pointers or references to base class objects. If a function is called using a base class pointer or reference, C++ determines which version of the function to call based on the actual object type (i.e., the type of the object the pointer/reference is pointing to).

    5. Destructor: If you have a base class with virtual functions, it is also important to declare the destructor as virtual to ensure proper cleanup of resources in derived class objects when they are deleted through base class pointers.


    Syntax of Virtual Functions

    class Base {
    public:
        // Declare a virtual function in the base class
        virtual void functionName();
    };
    
    class Derived : public Base {
    public:
        // Override the virtual function in the derived class
        void functionName() override;
    };
    

    Example 1: Basic Virtual Function Example

    #include <iostream>
    using namespace std;
    
    class Base {
    public:
        // Virtual function in the base class
        virtual void display() {
            cout << "Base class display function" << endl;
        }
    };
    
    class Derived : public Base {
    public:
        // Override the virtual function in the derived class
        void display() override {
            cout << "Derived class display function" << endl;
        }
    };
    
    int main() {
        Base *basePtr;
        Derived derivedObj;
    
        basePtr = &derivedObj;
    
        // Call the virtual function through the base class pointer
        basePtr->display();  // Output: Derived class display function
        
        return 0;
    }
    

    Explanation:

    • Base has a virtual function display(), and Derived overrides it.
    • A base class pointer basePtr is used to point to a Derived object.
    • When basePtr->display() is called, it invokes the overridden function in the derived class, showing the output from the Derived class, not the Base class.

    Important Points About Virtual Functions:

    1. Virtual Functions and Derived Class:

      • When a function in a derived class overrides a virtual function, the function in the derived class is called when accessed via a base class pointer or reference.
      • The keyword override (optional but recommended) in the derived class ensures that the function properly overrides a virtual function from the base class, helping to prevent accidental mistakes.
    2. Virtual Destructor:

      • If a class has virtual functions, it should also have a virtual destructor. This ensures that when an object is deleted via a base class pointer, the derived class destructor is called, allowing for proper resource cleanup.
    class Base {
    public:
        virtual ~Base() {  // Virtual destructor
            cout << "Base class destructor" << endl;
        }
    };
    
    class Derived : public Base {
    public:
        ~Derived() override {  // Overridden destructor
            cout << "Derived class destructor" << endl;
        }
    };
    
    1. Pure Virtual Functions (Abstract Classes):
      • A pure virtual function is a function that is declared in a base class but does not have any implementation. It forces derived classes to implement this function.
      • A class containing at least one pure virtual function is called an abstract class and cannot be instantiated directly.
    class Base {
    public:
        virtual void display() = 0;  // Pure virtual function
    };
    
    class Derived : public Base {
    public:
        void display() override {
            cout << "Derived class display function" << endl;
        }
    };
    

    Explanation:

    • The display() function is a pure virtual function (= 0), which means it must be overridden by any derived class.
    • The base class is now an abstract class, and objects of the base class cannot be instantiated directly.

    Example 2: Virtual Function with Destructor

    #include <iostream>
    using namespace std;
    
    class Base {
    public:
        Base() { cout << "Base class constructor" << endl; }
        virtual ~Base() { cout << "Base class destructor" << endl; }  // Virtual destructor
    };
    
    class Derived : public Base {
    public:
        Derived() { cout << "Derived class constructor" << endl; }
        ~Derived() override { cout << "Derived class destructor" << endl; }
    };
    
    int main() {
        Base *basePtr = new Derived();
        delete basePtr;  // Proper destruction of derived class object
        
        return 0;
    }
    

    Explanation:

    • In this example, the Base class has a virtual destructor, ensuring that when the base pointer basePtr is used to delete a Derived object, both the Derived and Base destructors are called.
    • Without the virtual destructor, only the base class destructor would be called, leading to incomplete cleanup of resources in the derived class.

    Output:

    Base class constructor
    Derived class constructor
    Derived class destructor
    Base class destructor
    

    Example 3: Virtual Functions and Multiple Levels of Inheritance

    #include <iostream>
    using namespace std;
    
    class Animal {
    public:
        virtual void sound() {
            cout << "Animal makes a sound" << endl;
        }
    };
    
    class Dog : public Animal {
    public:
        void sound() override {
            cout << "Dog barks" << endl;
        }
    };
    
    class Puppy : public Dog {
    public:
        void sound() override {
            cout << "Puppy whines" << endl;
        }
    };
    
    int main() {
        Animal *animalPtr;
        Dog dogObj;
        Puppy puppyObj;
    
        animalPtr = &dogObj;
        animalPtr->sound();  // Output: Dog barks
    
        animalPtr = &puppyObj;
        animalPtr->sound();  // Output: Puppy whines
        
        return 0;
    }
    

    Explanation:

    • Here, we have a class hierarchy: Animal → Dog → Puppy.
    • Even though the pointer animalPtr is of type Animal*, the correct function is called based on the actual object type (Dog or Puppy).
    • This is an example of multi-level inheritance with virtual functions.

    Output:

    Dog barks
    Puppy whines
    

    Benefits of Virtual Functions:

    1. Achieve Runtime Polymorphism: Virtual functions allow the correct function to be called based on the actual object type, enabling runtime polymorphism and making code more flexible.

    2. Dynamic Dispatch: By using virtual functions, C++ determines which function to call at runtime, based on the actual object type pointed to by the base class pointer or reference.

    3. Support for Abstract Classes: Virtual functions, especially pure virtual functions, support the creation of abstract classes that define common interfaces for derived classes.

    4. Proper Cleanup with Virtual Destructors: When you have a base class pointer that points to a derived class object, using a virtual destructor ensures that both base and derived class destructors are called, avoiding memory leaks.


    Conclusion

    Virtual functions are a fundamental concept in C++ that enable runtime polymorphism, making it possible to call the correct function for an object even when accessed through a pointer or reference to a base class. By using the virtual keyword, derived classes can override base class functions, and virtual destructors ensure proper object destruction. Virtual functions play a key role in object-oriented programming, providing flexibility, extensibility, and maintainability.

    Previous topic 10
    Function Overloading
    Next topic 12
    Derived Classes

    Past Papers

    Open this section to load past papers

    Click on Show Past Papers to see past papers.
    On This Page
      Reading Stats
      Est. reading time8 min
      Word count1,302
      Code examples0
      DifficultyIntermediate