Polymorphism is one of the core concepts of Object-Oriented Programming (OOP). The term "polymorphism" comes from Greek, meaning "many forms." In programming, polymorphism allows objects of different classes to be treated as objects of a common base class. It enables one interface to control access to a general class of actions, where specific actions are determined at runtime.
Polymorphism in C++ allows you to call derived class methods through a base class pointer or reference, providing flexibility and reusability in code.
There are two main types of polymorphism in C++:
Compile-time polymorphism is resolved during the compilation phase. The most common forms of compile-time polymorphism in C++ are:
Function overloading allows you to define multiple functions with the same name but with different parameters (either in number or type). The correct function is chosen at compile time based on the number and types of arguments passed.
#include <iostream>
using namespace std;
class Print {
public:
void show(int i) {
cout << "Integer: " << i << endl;
}
void show(double d) {
cout << "Double: " << d << endl;
}
void show(string s) {
cout << "String: " << s << endl;
}
};
int main() {
Print obj;
obj.show(5); // Calls the show(int) method
obj.show(3.14); // Calls the show(double) method
obj.show("Hello"); // Calls the show(string) method
return 0;
}
Explanation:
show() function is overloaded for different parameter types: int, double, and string.Output:
Integer: 5
Double: 3.14
String: Hello
Operator overloading allows you to define how operators work for user-defined types (like classes). You can provide custom behavior for operators such as +, -, =, etc.
#include <iostream>
using namespace std;
class Complex {
public:
int real, imag;
Complex() : real(0), imag(0) {}
Complex operator + (const Complex &c) {
Complex temp;
temp.real = real + c.real;
temp.imag = imag + c.imag;
return temp;
}
void display() {
cout << real << " + " << imag << "i" << endl;
}
};
int main() {
Complex c1, c2, c3;
c1.real = 3; c1.imag = 4;
c2.real = 1; c2.imag = 2;
c3 = c1 + c2; // Operator + is overloaded
c3.display(); // Output: 4 + 6i
return 0;
}
Explanation:
+ operator is overloaded to add two Complex objects.operator+ function, which adds the real and imaginary parts of two complex numbers.Output:
4 + 6i
Runtime polymorphism is resolved during the runtime of the program. The most common mechanism for achieving runtime polymorphism in C++ is through virtual functions. When a base class pointer or reference is used to point to a derived class object, the correct function is called based on the actual type of the object, not the type of the pointer.
A virtual function in the base class is overridden by the derived class, and the correct function is invoked based on the type of object being referred to, even when accessed through a base class pointer or reference.
#include <iostream>
using namespace std;
class Shape {
public:
virtual void draw() { // Virtual function
cout << "Drawing Shape" << endl;
}
};
class Circle : public Shape {
public:
void draw() override { // Override the base class method
cout << "Drawing Circle" << endl;
}
};
class Square : public Shape {
public:
void draw() override { // Override the base class method
cout << "Drawing Square" << endl;
}
};
int main() {
Shape* shape;
Circle circle;
Square square;
shape = &circle;
shape->draw(); // Calls Circle's draw() at runtime
shape = □
shape->draw(); // Calls Square's draw() at runtime
return 0;
}
Explanation:
draw() is a virtual function in the Shape class.Circle and Square classes override the draw() function.shape pointer being of type Shape*, the actual method that gets invoked is determined at runtime based on the type of the object (Circle or Square).Output:
Drawing Circle
Drawing Square
A pure virtual function makes a class abstract, meaning that it cannot be instantiated. Derived classes must provide an implementation for the pure virtual function.
#include <iostream>
using namespace std;
class Shape {
public:
virtual void draw() = 0; // Pure virtual function
};
class Circle : public Shape {
public:
void draw() override {
cout << "Drawing Circle" << endl;
}
};
int main() {
// Shape shape; // Error: cannot instantiate an abstract class
Circle circle;
circle.draw(); // Calls Circle's draw() method
return 0;
}
Explanation:
draw() method in Shape is a pure virtual function (= 0), making Shape an abstract class.Circle overrides the draw() method, and we can instantiate and use objects of Circle.Output:
Drawing Circle
Code Reusability: Polymorphism allows a base class reference or pointer to be used for objects of different derived classes. This makes the code more flexible and reusable.
Extensibility: New derived classes can be added without modifying the base class code, and the code that uses the base class can handle the new derived class objects seamlessly.
Maintainability: Polymorphism reduces the need for complex conditionals (like if or switch) to handle different object types. It provides cleaner and more maintainable code.
Flexibility: Through runtime polymorphism, the specific method of a derived class is called at runtime, depending on the object type, allowing for more dynamic and flexible program behavior.
Open this section to load past papers