Polymorphism in C++

Last Updated : 7 May, 2026

Polymorphism means “many forms”, where a single function or method can behave differently in different situations. In C++, it allows the same function to produce different outputs depending on the object that calls it.

  • Same function, different behavior depending on the object
  • Achieved through function overloading and function overriding
  • Helps improve code reusability and flexibility

Real-Life Illustration of Polymorphism

Different animals represent polymorphism, where the same method speak() produces different outputs such as Bark, Meow, and Moo depending on the object calling the method.

Polymorphysm
Polymorphism

In above Diagram:

  • A Dog object says Bark
  • A Cat object says Meow
  • A Cow object says Moo

Even though all animals use the same function name speak(), the behavior changes according to the object.

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

// Base class
class Animal {
public:

    // Virtual function
    virtual void speak() {
        cout << "Animal sound" << endl;
    }
};

// Derived class Dog
class Dog : public Animal{
    
public:
    void speak() {
        cout << "Bark" << endl;
    }
};

// Derived class Cat
class Cat : public Animal {
public:

    void speak(){
        
        cout << "Meow" << endl;
    }
};

int main(){

    // Base class pointer
    Animal* a;

    Dog d;
    Cat c;

    // Pointer refers to Dog object
    a = &d;
    a->speak();

    // Pointer refers to Cat object
    a = &c;
    a->speak();

    return 0;
}

Output
Bark
Meow

Explanation: In this program, the speak() function behaves differently depending on the object. When the pointer refers to the Dog object, it prints Bark, and when it refers to the Cat object, it prints Meow. This demonstrates runtime polymorphism in C++.

Types of Polymorphism

In C++, polymorphism is mainly divided into two types:

Poly
Types of Polymorphism

Compile-Time Polymorphism

Compile-time polymorphism is also known as static polymorphism or early binding. In this type of polymorphism, the compiler decides which function or operator to call during compilation. It is achieved using:

1. Function Overloading

Function Overloading allows multiple functions to have the same name but different parameters. The difference can be in:

  • Number of parameters
  • Type of parameters

The compiler selects the correct function based on the arguments passed during the function call.

C++
#include <bits/stdc++.h>
using namespace std;

class Geeks {
public:
    
    // Function to add two integers
    void add(int a, int b) {
        cout << "Integer Sum = " << a + b
        << endl;
    }
    
    // Function to add two floating point values
    void add(double a, double b) {
        cout << "Float Sum = " << a + b
        << endl ;
    }
};

int main() {
    Geeks gfg;
    
    // add() called with int values
    gfg.add(10, 2);

    // add() called with double value
    gfg.add(5.3, 6.2);

    return 0;
}

Output
Integer Sum = 12
Float Sum = 11.5

Explanation: In the above example, two add() functions are defined with the same name but different parameter types: one for integers and one for floating-point numbers. The correct version of the add() function is called at compile time based on the type of arguments passed, allowing the same function name to be used for different data types.

2. Operator Overloading

Operator overloading allows operators such as +, -, and * to work with user-defined data types. For example:

  • The + operator adds two integers.
  • The same + operator can concatenate two strings.
  • We can also define how + should behave for custom classes.

This makes code more readable and natural.

Note: Most operators in C++ can be overloaded, but operators such as ::, ., .*, ?:, and sizeof cannot be overloaded because they are essential to the core functionality of the language.

CPP
#include <iostream>
using namespace std;

class Complex {
public:
    int real, imag;
    
    Complex(int r, int i) :
    real(r), imag(i) {}

    // Overloading the '+' operator
    Complex operator+(const Complex& obj) {
        return Complex(real + obj.real,
        imag + obj.imag);
    }
};

int main() {
    Complex c1(10, 5), c2(2, 4);
    
    // Adding c1 and c2 using + operator
    Complex c3 = c1 + c2;  
    cout << c3.real << " + i" << c3.imag;
    return 0;
}

Output
12 + i9

Explanation: Above program demonstrates operator overloading in C++ by redefining the + operator for the Complex class. The overloaded operator adds the real and imaginary parts of two complex number objects. When c1 + c2 is executed, the overloaded + operator is called automatically, and the result is stored in c3. The final output displays the sum of the two complex numbers.

2. Runtime Polymorphism

Runtime polymorphism is also known as dynamic polymorphism or late binding. In this type, the function call is resolved during program execution instead of compilation. It is achieved using:

1. Function Overriding

Function Overriding occurs when a derived class defines one or more member functions of the base class. That base function is said to be overridden. The base class function must be declared as virtual function for runtime polymorphism to happen.

C++
#include <bits/stdc++.h>
using namespace std;

class Base {
public:

    // Virtual function
    virtual void display() {
        cout << "Base class function";
    }
};

class Derived : public Base {
public:

    // Overriding the base class function
    void display() override {
        cout << "Derived class function";
    }
};

int main() {
    
    // Creating a pointer of type Base
    Base* basePtr;
    
    // Creating an object of Derived class
    Derived derivedObj;

    // Pointing base class pointer to 
    // derived class object
    basePtr = &derivedObj;
    
    // Calling the display function 
    // using base class pointer
    basePtr->display();
    return 0;
}

Output
Derived class function

Explanation: In the above example, a virtual function display() is defined in the base class Base, and it is overridden in the derived class Derived. The Base class pointer basePtr points to an object of the Derived class. When the display() function is called using the basePtr, the derived class version of the display() function is called, and prints "Derived class function." This is possible because call is resolved at the runtime.

Runtime vs Compiler Time Polymorphism

The major difference between the compile-time and runtime polymorphism is:

Compile Time Polymorphism

Run time Polymorphism

Also called static binding

Also called dynamic binding

Achieved using function overloading and operator overloading

Achieved using virtual functions and function overriding

Decision made by the compiler at compile time

Decision made at runtime using vtables

Faster due to early binding

More flexible but slightly slower

Comment