C++ Polymorphism
Overview
Polymorphism allows objects of different classes to be treated as objects of a common superclass. The most common use of polymorphism is when a parent class reference is used to refer to a child class object.
Compile-time Polymorphism (Function Overloading)
cpp
#include <iostream>
class Calculator {
public:
// Function overloading
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
std::string add(const std::string& a, const std::string& b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
};
int main() {
Calculator calc;
std::cout << "Int addition: " << calc.add(5, 3) << std::endl;
std::cout << "Double addition: " << calc.add(2.5, 3.7) << std::endl;
std::cout << "String addition: " << calc.add("Hello", "World") << std::endl;
std::cout << "Three numbers: " << calc.add(1, 2, 3) << std::endl;
return 0;
}Operator Overloading
cpp
#include <iostream>
class Complex {
private:
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// Overload + operator
Complex operator+(const Complex& other) {
return Complex(real + other.real, imag + other.imag);
}
// Overload << operator for output
friend std::ostream& operator<<(std::ostream& os, const Complex& c) {
os << c.real;
if (c.imag >= 0) os << "+";
os << c.imag << "i";
return os;
}
// Overload == operator
bool operator==(const Complex& other) {
return real == other.real && imag == other.imag;
}
};
int main() {
Complex c1(3.0, 4.0);
Complex c2(1.0, 2.0);
Complex c3 = c1 + c2;
std::cout << "c1: " << c1 << std::endl;
std::cout << "c2: " << c2 << std::endl;
std::cout << "c1 + c2: " << c3 << std::endl;
if (c1 == Complex(3.0, 4.0)) {
std::cout << "c1 equals (3.0, 4.0)" << std::endl;
}
return 0;
}Runtime Polymorphism (Virtual Functions)
cpp
#include <iostream>
#include <vector>
class Animal {
public:
// Virtual function
virtual void makeSound() {
std::cout << "Some generic animal sound" << std::endl;
}
// Pure virtual function (makes class abstract)
virtual void move() = 0;
virtual ~Animal() {} // Virtual destructor
};
class Dog : public Animal {
public:
void makeSound() override {
std::cout << "Woof! Woof!" << std::endl;
}
void move() override {
std::cout << "Dog is running" << std::endl;
}
};
class Cat : public Animal {
public:
void makeSound() override {
std::cout << "Meow! Meow!" << std::endl;
}
void move() override {
std::cout << "Cat is walking gracefully" << std::endl;
}
};
class Bird : public Animal {
public:
void makeSound() override {
std::cout << "Tweet! Tweet!" << std::endl;
}
void move() override {
std::cout << "Bird is flying" << std::endl;
}
};
int main() {
// Array of base class pointers
std::vector<Animal*> animals;
animals.push_back(new Dog());
animals.push_back(new Cat());
animals.push_back(new Bird());
// Polymorphic behavior
for (Animal* animal : animals) {
animal->makeSound();
animal->move();
std::cout << "---" << std::endl;
}
// Clean up
for (Animal* animal : animals) {
delete animal;
}
return 0;
}Abstract Classes and Interfaces
cpp
#include <iostream>
// Abstract class (interface)
class Drawable {
public:
// Pure virtual functions
virtual void draw() = 0;
virtual void resize(double factor) = 0;
virtual ~Drawable() {}
};
class Shape : public Drawable {
protected:
double x, y; // Position
public:
Shape(double x_pos, double y_pos) : x(x_pos), y(y_pos) {}
void move(double dx, double dy) {
x += dx;
y += dy;
std::cout << "Shape moved to (" << x << ", " << y << ")" << std::endl;
}
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double x, double y, double r) : Shape(x, y), radius(r) {}
void draw() override {
std::cout << "Drawing circle at (" << x << ", " << y
<< ") with radius " << radius << std::endl;
}
void resize(double factor) override {
radius *= factor;
std::cout << "Circle resized to radius " << radius << std::endl;
}
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double x, double y, double w, double h)
: Shape(x, y), width(w), height(h) {}
void draw() override {
std::cout << "Drawing rectangle at (" << x << ", " << y
<< ") with width " << width << " and height " << height << std::endl;
}
void resize(double factor) override {
width *= factor;
height *= factor;
std::cout << "Rectangle resized to " << width << " x " << height << std::endl;
}
};
int main() {
Drawable* shapes[2];
shapes[0] = new Circle(10, 20, 5.0);
shapes[1] = new Rectangle(30, 40, 8.0, 6.0);
for (int i = 0; i < 2; i++) {
shapes[i]->draw();
shapes[i]->resize(1.5);
shapes[i]->draw();
std::cout << "---" << std::endl;
}
// Clean up
for (int i = 0; i < 2; i++) {
delete shapes[i];
}
return 0;
}