EZ

Eduzan

Learning Hub

Eduzan
Eduzan / C++

Polymorphism

Polymorphism, derived from the term meaning “many forms,” refers to the ability of an entity to take on different behaviors or forms depending on the context. In Object-Oriented Programming (OOP), polymorphism is a core feature that enables a single action to be performed in various ways, depending on the object that invokes it. A common real-world example is a person who assumes different roles simultaneously, such as being a parent, an employee, and a friend. Similarly, polymorphism allows objects of different classes to respond uniquely to the same function call, making it a fundamental concept in OOP.

Types of Polymorphism:

1. Compile-Time Polymorphism (also called early binding or static polymorphism)
2. Run-Time Polymorphism (also known as late binding or dynamic polymorphism)

1. Compile-Time Polymorphism:

This type of polymorphism is achieved using function overloading or operator overloading.

A. Function Overloading:

In function overloading, multiple functions share the same name but differ in the number or type of parameters. Depending on the arguments passed, the appropriate function is selected at compile time.

Example of Function Overloading in C++:

#include <iostream>
using namespace std;

class Example {
public:
    void display(int a) {
        cout << "Integer: " << a << endl;
    }

    void display(double b) {
        cout << "Double: " << b << endl;
    }

    void display(int a, int b) {
        cout << "Two Integers: " << a << " and " << b << endl;
    }
};

int main() {
    Example obj;

    obj.display(5);        // Calls the function with an integer argument
    obj.display(3.14);     // Calls the function with a double argument
    obj.display(7, 8);     // Calls the function with two integer arguments
}

Output:

Integer: 5
Double: 3.14
Two Integers: 7 and 8

In this example, the display function behaves differently based on the type and number of arguments passed to it, demonstrating compile-time polymorphism.

B. Operator Overloading:

Operator overloading allows you to redefine the meaning of operators for user-defined types. For instance, the + operator can be overloaded to work with objects like complex numbers.

Example of Operator Overloading in C++:

#include <iostream>
using namespace std;

class Complex {
private:
    int real, imag;

public:
    Complex(int r = 0, int i = 0) : real(r), imag(i) {}

    // Overloading the '+' operator for complex numbers
    Complex operator+(const Complex& obj) {
        Complex res;
        res.real = real + obj.real;
        res.imag = imag + obj.imag;
        return res;
    }

    void display() const {
        cout << real << " + i" << imag << endl;
    }
};

int main() {
    Complex c1(3, 4), c2(1, 2);
    Complex c3 = c1 + c2;  // Calls overloaded '+' operator
    c3.display();
}

Output:

4 + i6

Here, the + operator is overloaded to add complex numbers, showing compile-time polymorphism using operator overloading.

2. Run-Time Polymorphism

This type of polymorphism is accomplished using function overriding, where a derived class provides a specific implementation of a function that is already defined in its base class. This allows the correct function to be called based on the object type at runtime.

A. Function Overriding:

When a derived class defines a function that overrides a function in its base class, the base function is “overridden.” The decision to call the base or derived class function is made at runtime.

Example of Function Overriding in C++:

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void sound() {
        cout << "Animal makes a sound" << endl;
    }
};

class Dog : public Animal {
public:
    void sound() override {
        cout << "Dog barks" << endl;
    }
};

int main() {
    Animal* animalPtr;
    Dog dog;

    animalPtr = &dog;
    animalPtr->sound();  // Calls the overridden method in the Dog class
}

Output:

Dog barks

In this example, the sound method is overridden in the Dog class, and the function call is resolved at runtime based on the actual object type.

B. Virtual Function:

virtual function in a base class allows derived classes to override it. When a base class pointer points to a derived class object, the overridden function is called, enabling run-time polymorphism.

Example of Virtual Function in C++:

#include <iostream>
using namespace std;

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

    void display() {
        cout << "Base class display function" << endl;
    }
};

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

    void display() {
        cout << "Derived class display function" << endl;
    }
};

int main() {
    Base* basePtr;
    Derived derivedObj;

    basePtr = &derivedObj;

    basePtr->show();     // Calls the overridden show() in Derived class
    basePtr->display();  // Calls the display() in Base class
}

Output:

Derived class show function
Base class display function
End of lesson.