C++ Polymorphism Explained | Function Overloading, Overriding, Virtual Functions, Runtime & Compile-Time Polymorphism


This complete tutorial on C++ Polymorphism explains how objects and functions can exhibit multiple behaviors. It covers function overloading, function overriding, compile-time polymorphism, runtime polymorphism, virtual functions, and the override keyword. The tutorial follows best practices and helps learners understand one of the core concepts of Object-Oriented Programming for flexible and reusable code.

Polymorphism – Complete Tutorial

1. What is Polymorphism?

Polymorphism is an OOP concept that allows a function or object to take multiple forms.

It increases flexibility and code reusability.

  1. Compile-time polymorphism (static) – resolved at compile time
  2. Runtime polymorphism (dynamic) – resolved at runtime

2. Function Overloading

Function overloading allows multiple functions with the same name but different parameter lists in the same scope.

Example:


#include <iostream>
using namespace std;

class Math {
public:
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
};

int main() {
Math m;
cout << m.add(5, 3) << endl; // Calls int version
cout << m.add(2.5, 3.5) << endl; // Calls double version
}

Best Practices:

  1. Use function overloading for similar operations
  2. Keep parameter types or number distinct

3. Function Overriding

Function overriding occurs when a derived class redefines a base class function with the same name, parameters, and return type.

Example:


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

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

int main() {
Derived d;
d.show(); // Calls derived class function
}

4. Compile-Time Polymorphism

Also called static polymorphism, resolved during compilation.

Examples:

  1. Function overloading
  2. Operator overloading

Key Point: Compiler decides which function/operator to call.

5. Runtime Polymorphism

Also called dynamic polymorphism, resolved at runtime.

Achieved using:

  1. Pointers or references to base class
  2. Virtual functions

Example:


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

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

int main() {
Base* b;
Derived d;
b = &d;
b->show(); // Calls derived class function at runtime
}

6. Virtual Functions

A virtual function is declared with the virtual keyword in the base class.

It allows runtime polymorphism.


class Base {
public:
virtual void display() { cout << "Base Display" << endl; }
};

Key Points:

  1. Enables derived class methods to be called through base class pointers
  2. Reduces the need for multiple conditional checks
  3. Always make base class destructor virtual if using inheritance

7. override Keyword

The override keyword explicitly tells the compiler that a function overrides a base class virtual function.

Example:


class Derived : public Base {
public:
void display() override { cout << "Derived Display" << endl; }
};

Benefits:

  1. Catches errors at compile time if function signatures don’t match
  2. Improves code readability

Best Practices for Polymorphism

  1. Use compile-time polymorphism for efficiency
  2. Use runtime polymorphism for flexibility
  3. Always mark base class destructor as virtual
  4. Prefer override for clarity and safety
  5. Avoid excessive multiple inheritance to reduce complexity

Common Mistakes

  1. Forgetting virtual keyword for base class functions
  2. Not using override when overriding
  3. Trying to override non-virtual functions
  4. Using base class object instead of pointer/reference for runtime polymorphism

Summary

In this chapter, you learned about C++ Polymorphism, including:

  1. Function overloading and overriding
  2. Compile-time and runtime polymorphism
  3. Virtual functions and override keyword

Polymorphism is a core OOP concept that allows flexible and reusable code, making programs easier to maintain and extend.