Introduction to Polymorphism

Definition

  • Polymorphism literally means “many forms”.

  • In programming, it refers to the ability of a function, object, or operator to behave differently in different situations.

Key Idea:

  • One name → multiple behaviors

  • Helps reuse code, improve flexibility, and model real-world systems

Real-World Analogy:

  1. Person:

    • One person can talk, walk, write, play football → same person, many forms of behavior

  2. Printer:

    • print() function can print text, images, PDF, or document → same function, multiple forms

Advantages of Polymorphism

  1. Code Reusability → Same function name works with different objects

  2. Maintainability → Changes in base class automatically reflect in derived classes

  3. Flexibility → Same interface works for different types

  4. Real-world modeling → Matches hierarchical relationships in real systems

Limitations of Polymorphism

  1. Slightly slower performance for run-time polymorphism (virtual functions)

  2. Can lead to confusion if overused without proper design

  3. Requires careful memory management for object pointers in inheritance

Types of Polymorphism

Compile-Time Polymorphism (Static Binding)

  • Also called early binding

  • Determined at compile time

  • Achieved via:

    1. Function Overloading

    2. Operator Overloading

Example (Function Overloading):

 
#include <iostream>

using namespace std;
class Calculator {
public:
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() {
Calculator calc;
cout << calc.add(2, 3) << endl; // calls int add(int,int)

cout << calc.add(2.5, 3.5) << endl; // calls double add(double,double)

cout << calc.add(1, 2, 3) << endl; // calls int add(int,int,int)
}

Practice Exercises:

  • Create a multiply() function with 2, 3, or double parameters

  • Create a volume() function for cube, cuboid, and cylinder

Run-Time Polymorphism (Dynamic Binding)

  • Also called late binding

  • Determined at runtime

  • Achieved via:

    1. Virtual Functions

    2. Function Overriding

Key Concept:

  • Virtual functions allow derived class methods to replace base class methods at runtime

Example (Virtual Function):

 
#include <iostream>
using namespace std;
class Animal {
public:
virtual void sound() {
cout << "Some sound" << endl;
}
};
class Dog :
public Animal {
public:
void sound()
override {
cout << "Bark" << endl;
}
};
class Cat :
public Animal {
public:
void sound()
override {
cout << "Meow" << endl;
}
};
int main() {
Animal* a1 = new Dog();
Animal* a2 = new Cat();
a1->sound(); // Bark

a2->sound(); // Meow
}

Practice Exercises:

  • Create Bird class with virtual fly() method

  • Override in Eagle and Parrot

  • Use base class pointer to call fly()

Function Overloading

Definition

  • Same function name with different parameters in the same scope

Rules:

  1. Different number of parameters

  2. Different type of parameters

  3. Return type alone cannot differentiate overloaded functions

Real-Life Analogy:

  • print() function prints text, image, or PDF → same name, multiple forms

Advantages:

  • Easier to read code

  • Flexible interfaces

  • Maintains same function names for related operations

Limitations:

  • Cannot overload by return type only

  • Too many overloaded functions can confuse programmers

Example:

 
#include <iostream>
using namespace std;
class Shape {
public:
void area(int side) {
cout << "Square Area: " << side*side << endl;
}
void area(int length, int width) {
cout << "Rectangle Area: " << length*width << endl;
}
void area(double radius) {
cout << "Circle Area: " << 3.14*radius*radius << endl;
}
};
int main() {
Shape s;
s.area(5);
s.area(4, 6);
s.area(3.5);
}

Practice Exercises:

  • Overload a volume() function for cube, cuboid, cylinder, and sphere

  • Overload display() to print int, double, and string

Virtual Functions

Definition

  • Virtual functions are functions in base class declared with virtual keyword

  • Can be overridden in derived class

  • Decision which function to call → runtime

Memory Concept:

  • Virtual Table (vtable) in C++ stores addresses of virtual functions

  • Base class pointer uses vtable to call correct derived function

Example:

 
#include <iostream>
using namespace std;
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* ptr;
Derived d;
ptr = &d;
ptr->show(); // Derived class

}

Practice Exercises:

  • Create Employee base class with virtual calculateSalary()

  • Derived classes: Manager, Developer → override calculateSalary()

  • Use base class pointer to call calculateSalary()

Advantages of Polymorphism

FeatureDescription
Code ReusabilityUse same function name for different operations
FlexibilityObjects behave differently at runtime
Real-World ModelingMimics human/real-world behavior
MaintainabilityChanges in base class automatically reflect in derived classes

Limitations

LimitationReason
Slight runtime overheadVirtual function pointer lookup
ComplexityHarder for beginners to trace
AmbiguityMultiple inheritance + same function names
Cannot overload only by return typeCompile-time conflict

Extra Real-Life Examples

  1. Banking System:

    • Base: Account → virtual calculateInterest()

    • Derived: SavingsAccount, CurrentAccount → override method

  2. School System:

    • Base: Person → virtual displayInfo()

    • Derived: Student, Teacher → override

  3. Transport:

    • Base: Vehicle → virtual start()

    • Derived: Car, Bike → override

Extended Exercises for Students

  1. Polymorphism + Overloading Practice:

    • Class Calculator with overloaded add(), subtract(), multiply()

    • Use base class pointer for run-time polymorphism

  2. Virtual Functions Exercise:

    • Base class Shape with virtual area()

    • Derived: Circle, Rectangle, Triangle → override area()

    • Use base class pointer to call area()

  3. Mixed Exercise:

    • Class hierarchy Employee → Manager/Developer

    • Function overloading: bonus() for full-time, part-time

    • Virtual function: calculateSalary()