Polymorphism in C++

Polymorphism means "many forms." In C++, it allows the same function name or operator to behave differently depending on the context. It is one of the most powerful features of OOP and enables flexible, extensible program design.

Types of Polymorphism in C++

TypeAlso Known AsResolved At
Compile-time (Static)Function/Operator OverloadingCompile time
Runtime (Dynamic)Virtual Functions / OverridingRuntime

Compile-Time Polymorphism — Function Overloading

Multiple functions can share the same name but differ in the number or type of parameters:

#include <iostream>
using namespace std;

int add(int a, int b)          { return a + b; }
double add(double a, double b) { return a + b; }
int add(int a, int b, int c)   { return a + b + c; }

int main() {
    cout << add(3, 4)       << endl;   // 7
    cout << add(2.5, 3.5)   << endl;   // 6.0
    cout << add(1, 2, 3)    << endl;   // 6
    return 0;
}

Output:

7
6
6

Runtime Polymorphism — Virtual Functions

Runtime polymorphism is achieved through virtual functions and function overriding. When a base class pointer or reference calls a virtual function, C++ decides at runtime which version to call based on the actual object type.

Without Virtual Function (wrong behavior):

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

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

int main() {
    Shape *ptr = new Circle();
    ptr->draw();   // Calls Shape::draw — NOT Circle::draw!
    return 0;
}

Output (unexpected):

Drawing Shape

With Virtual Function (correct behavior):

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

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

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

int main() {
    Shape *ptr;

    ptr = new Circle();
    ptr->draw();    // Calls Circle::draw

    ptr = new Square();
    ptr->draw();    // Calls Square::draw

    return 0;
}

Output:

Drawing Circle
Drawing Square

The override Keyword

Using override explicitly tells the compiler that the function is intentionally overriding a virtual function. It catches typos and mismatches at compile time.

Pure Virtual Functions and Abstract Classes

A pure virtual function has no implementation in the base class. A class with at least one pure virtual function becomes an abstract class — it cannot be instantiated directly.

class Animal {
public:
    virtual void speak() = 0;   // pure virtual function
};

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

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

int main() {
    Animal *a;

    a = new Cat();
    a->speak();    // Meow!

    a = new Dog();
    a->speak();    // Woof!

    return 0;
}

Output:

Meow!
Woof!

Virtual Destructor

When using base class pointers with derived objects, the destructor should be virtual to ensure the correct destructor is called:

class Base {
public:
    virtual ~Base() { cout << "Base destroyed" << endl; }
};

class Derived : public Base {
public:
    ~Derived() { cout << "Derived destroyed" << endl; }
};

int main() {
    Base *b = new Derived();
    delete b;   // Calls Derived::~Derived() then Base::~Base()
    return 0;
}

Output:

Derived destroyed
Base destroyed

Key Takeaways

  • Polymorphism allows the same interface to behave differently for different types.
  • Compile-time polymorphism is achieved through function overloading.
  • Runtime polymorphism is achieved through virtual functions and overriding.
  • Mark base class functions with virtual to enable runtime dispatch.
  • Use override in derived classes for safety and clarity.
  • Abstract classes with pure virtual functions define interfaces that subclasses must implement.
  • Always make the base class destructor virtual when using polymorphism.

Leave a Comment

Your email address will not be published. Required fields are marked *