←Back to Subject
Notes
Notes
Study material and explanations
Diagrams
Diagrams
Visualize concepts easily
Mnemonics
Mnemonics
Tricks to remember faster
One Night Prep
One Night Prep
Short and focused revision
Revision
Revision
Quick summary and key points
Important Questions
Important Questions
Practice most relevant questions
Notes

Virtual Functions, Abstract Classes & Runtime Polymorphism

Study material and explanations for Unit 5

Virtual Functions, Abstract Classes & Runtime Polymorphism

1. What is Polymorphism? (In Simple Words)

The word Polymorphism comes from two Greek words: Poly (meaning many) and Morph (meaning forms).

In programming, it means one name, many different behaviors.

C++ has two types of Polymorphism:

The Two Branches of Polymorphism in C++
1. Compile-Time (Early / Static Binding)
The compiler decides which function to call while compiling the code. Fast and fixed.
• Function Overloading
• Operator Overloading
2. Run-Time (Late / Dynamic Binding)
The decision of which function to call is delayed until the program actually runs, based on the real object in RAM.
• Virtual Functions

2. The Problem: Base Pointer to Derived Object

In C++, a parent (base) pointer is allowed to hold the address of any child (derived) object:

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

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

int main() {
    Base *ptr;
    Derived objD;
    ptr = &objD; // Parent pointer points to Child object!

    ptr->show(); // Prints: "Base show()", NOT Derived!
    return 0;
}

Why did this happen?

By default, C++ uses Early Binding (Compile-Time Binding). The compiler looks only at the type of the pointer (Base*), ignoring the fact that it is actually holding a Derived object!


3. The Solution: Virtual Functions (Late Binding)

To fix this, we put the virtual keyword before the function in the base class:

“Hey compiler! Don’t decide which function to run right now. Wait until runtime, check what object is actually inside the pointer, and run that object’s function!”

#include <iostream>
using namespace std;

class Animal {
    public:
        // VIRTUAL FUNCTION: Enables Runtime Polymorphism!
        virtual void makeSound() { 
            cout << "Animal makes a sound" << endl; 
        }
};

class Dog : public Animal {
    public:
        void makeSound() override { 
            cout << "Dog barks: Woof! Woof!" << endl; 
        }
};

class Cat : public Animal {
    public:
        void makeSound() override { 
            cout << "Cat meows: Meow! Meow!" << endl; 
        }
};

int main() {
    Animal *ptr; // Base class pointer

    Dog d;
    Cat c;

    ptr = &d;
    ptr->makeSound(); // Prints: Dog barks: Woof! Woof!

    ptr = &c;
    ptr->makeSound(); // Prints: Cat meows: Meow! Meow!

    return 0;
}

4. Pure Virtual Functions & Abstract Classes

Imagine you have a base class called Shape. How would you write the formula for Shape::area()? You can’t! Because you don’t know whether the shape is a circle, rectangle, or triangle.

A Pure Virtual Function is a virtual function in a base class that has no code body at all and is set to zero (= 0):

virtual void area() = 0; // Pure Virtual Function

What is an Abstract Class?

An Abstract Class is any class that contains at least one Pure Virtual Function.

Rules of Abstract Classes
No Direct Objects
You CANNOT create direct objects of an abstract class (Shape s; will give an error!).
Pointers are Allowed
You CAN create pointers to an abstract class (Shape *ptr;) to achieve runtime polymorphism.
Mandatory Overriding
Every derived child class MUST override and provide code for all pure virtual functions, or it becomes abstract too!
Acts as a Blueprint Contract
Ensures that every child shape will definitely implement area().

5. Complete Practical Example: Shape Hierarchy

#include <iostream>
using namespace std;

// 1. ABSTRACT BASE CLASS
class Shape {
    public:
        // Pure Virtual Function
        virtual void area() const = 0; 

        // Virtual Destructor (Best Practice)
        virtual ~Shape() {} 
};

// 2. CHILD CLASS 1
class Circle : public Shape {
    private:
        float radius;

    public:
        Circle(float r) : radius(r) {}
        
        void area() const override {
            cout << "Area of Circle: " << (3.14159f * radius * radius) << endl;
        }
};

// 3. CHILD CLASS 2
class Rectangle : public Shape {
    private:
        float length, width;

    public:
        Rectangle(float l, float w) : length(l), width(w) {}

        void area() const override {
            cout << "Area of Rectangle: " << (length * width) << endl;
        }
};

int main() {
    // Shape s; // COMPILER ERROR: Cannot create object of an abstract class!

    Shape *shapePtr; // Base pointer is allowed!

    Circle c(5.0f);
    Rectangle r(4.0f, 6.0f);

    shapePtr = &c;
    shapePtr->area(); // Prints: Area of Circle: 78.5398

    shapePtr = &r;
    shapePtr->area(); // Prints: Area of Rectangle: 24

    return 0;
}

DAVV Exam Preparation Tips

Frequently Asked 5-Mark Questions:

  1. Differentiate between Compile-Time and Run-Time Polymorphism.
    Model Answer:
    • Compile-Time (Early Binding): Decided by compiler during build time. Includes Function Overloading and Operator Overloading. Faster execution.
    • Run-Time (Late Binding): Decided during program execution based on the object pointed to. Implemented using Virtual Functions.
  2. What is an Abstract Class? State two properties.
    Model Answer:
    • A class that has at least one pure virtual function (virtual void func() = 0;).
    • Properties: Cannot create direct objects; can create base pointers; derived classes must override pure virtual functions.

Frequently Asked 10-Mark Questions:

  1. Explain Virtual Functions and Late Binding in C++. What is a Pure Virtual Function? Write a complete C++ program demonstrating an abstract Shape class with derived Circle and Rectangle classes.
    Model Answer:
    • Explain why early binding fails when a base pointer holds a derived object.
    • Explain how virtual achieves late binding using internal VTABLE (Virtual Table) and VPTR (Virtual Pointer).
    • Define pure virtual function (= 0) and abstract class.
    • Write out the complete C++ Shape program with Circle and Rectangle implementations and output trace.