Introduction
Polymorphism is one of the four fundamental principles of Object-Oriented Programming (OOP), enabling objects to behave differently based on the context. The word “polymorphism” means “many forms,” and in C++, it allows the same function or operator to perform differently for different types or objects. It promotes flexibility and reusability by allowing common interfaces for various data types. C++ supports two types of polymorphism: compile-time (static) and run-time (dynamic). Function overloading and operator overloading are examples of compile-time polymorphism. Virtual functions and base class pointers enable runtime polymorphism. It helps simplify complex codebases by offering clean abstraction and modular design.
13.1 Types of Polymorphism in C++
- Compile-Time Polymorphism
Also known as static polymorphism, it is resolved during the compilation process. It allows function or operator to be overloaded, meaning you can have multiple versions of the same function/operator with different signatures.
➤ Function Overloading
Multiple functions with the same name but different parameters. Compiler determines the correct function to invoke at compile time.
General Syntax:
class Demo {
public:
void show(); // No parameter
void show(int a); // One int parameter
void show(double a); // One double parameter
};
Example:
#include <iostream>
using namespace std;
class Demo {
public:
void show() {
cout << “No parameter” << endl;
}
void show(int a) {
cout << “Integer: ” << a << endl;
}
void show(double a) {
cout << “Double: ” << a << endl;
}
};
int main() {
Demo d;
d.show();
d.show(5);
d.show(3.14);
return 0;
}
➤ Operator Overloading
Allows you to redefine the meaning of an operator (like +, -, ==) for user-defined types.
General Syntax:
class ClassName {
int val;
public:
ClassName(int v);
ClassName operator+(const ClassName& obj);
};
Example:
#include <iostream>
using namespace std;
class Box {
int length;
public:
Box(int l) : length(l) {}
Box operator+(const Box& b) {
return Box(length + b.length);
}
void show() {
cout << “Length: ” << length << endl;
}
};
int main() {
Box b1(10), b2(15);
Box b3 = b1 + b2;
b3.show();
return 0;
}
- Runtime Polymorphism
Also known as dynamic polymorphism, it is achieved using virtual functions and base class pointers. The decision of which function to invoke is made at runtime based on the actual object type.
➤ Virtual Functions
Used in base class and overridden in derived classes. Enables runtime decision using base class pointer or reference.
General Syntax:
class Base {
public:
virtual void display();
};
class Derived : public Base {
public:
void display();
};
Example:
#include <iostream>
using namespace std;
class Base {
public:
virtual void show() {
cout << “Base class show()” << endl;
}
};
class Derived : public Base {
public:
void show() override {
cout << “Derived class show()” << endl;
}
};
int main() {
Base* ptr;
Derived d;
ptr = &d;
ptr->show(); // Runtime decision
return 0;
}
Function Overriding
Occurs when a derived class provides a new implementation of a function already defined in its base class. It requires the use of virtual in the base class.
General Syntax:
class Base {
public:
virtual void print();
};
class Derived : public Base {
public:
void print(); // Overrides base version
};
Example:
#include <iostream>
using namespace std;
class Animal {
public:
virtual void sound() {
cout << “Animal makes sound” << endl;
}
};
class Dog : public Animal {
public:
void sound() override {
cout << “Dog barks” << endl;
}
};
int main() {
Animal* a;
Dog d;
a = &d;
a->sound();
return 0;
}