Extra 5% OFF Use Code: OL05
Free Shipping over ₹999

Polymorphism

Introduction

Polymorphism in Object Oriented programming means “many forms.” It allows one function, method, or operator to behave differently based on the object or data it’s working with.

In C++, there are two types of polymorphism:

Compile-Time Polymorphism (Static Binding)

Compile-time polymorphism, also known as static binding or early binding, happens when the method or function to be executed is determined during compilation. It is typically achieved through:

Function Overloading:

Multiple functions with the same name but different parameter types.

For example

#include <iostream>
using namespace std;

class Calculator {
public:
    // Function to add two integers
    int add(int a, int b) {
        return a + b;
    }
    
    // Function to add two double values
    double add(double a, double b) {
        return a + b;
    }
    
    // Function to add three integers
    int add(int a, int b, int c) {
        return a + b + c;
    }
};

int main() {
    Calculator calc;

    cout << "Sum of two integers: " << calc.add(10, 20) << endl;      // Calls int version
    cout << "Sum of two doubles: " << calc.add(5.5, 10.5) << endl;    // Calls double version
    cout << "Sum of three integers: " << calc.add(1, 2, 3) << endl;   // Calls three-argument version

    return 0;
}

Output:

Sum of two integers: 30
Sum of two doubles: 16
Sum of three integers: 6

Explanation:

Step 1: Class Declaration:

class Calculator {
public:
    // Function declarations go here
};
  • The Calculator class contains three overloaded add() functions that handle different numbers and types of arguments.

Step 2: First add() Function: Add Two Integers:

int add(int a, int b) {
    return a + b;
}
  • This function takes two integers as input and returns their sum.
  • Example call: calc.add(10, 20); calls this version of the function because both arguments are integers.

Step 3: Second add() Function: Add Two Double Values:

double add(double a, double b) {
    return a + b;
}
  • This function takes two double values as input and returns their sum.
  • Example call: calc.add(5.5, 10.5); calls this version of the function because both arguments are of type double

Step 4: Third add() Function: Add Three Integers:

int add(int a, int b, int c) {
    return a + b + c;
}
  • This function takes three integers as input and returns their sum.
  • Example call: calc.add(1, 2, 3); calls this version of the function because it has three integer arguments.

Step 5: Main Function:

int main() {
    Calculator calc;

    cout << "Sum of two integers: " << calc.add(10, 20) << endl;      // Calls int version
    cout << "Sum of two doubles: " << calc.add(5.5, 10.5) << endl;    // Calls double version
    cout << "Sum of three integers: " << calc.add(1, 2, 3) << endl;   // Calls three-argument version

    return 0;
}
  • In the main() function, an object calc of class Calculator is created.
  • We call the add() function three times with different arguments:
    • calc.add(10, 20) calls the first version (with two integers).
    • calc.add(5.5, 10.5) calls the second version (with two doubles).
    • calc.add(1, 2, 3) calls the third version (with three integers).

Operator Overloading:

Operator overloading is a feature in Object-Oriented Programming (OOP) that allows you to define how operators like +, -, *, and == behave when applied to user-defined data types (like objects of a class). The same operator behaves differently based on the types of operands.

For example:

#include <iostream>
using namespace std;

class Point {
private:
    int x, y;

public:
    // Constructor to initialize the point
    Point(int a = 0, int b = 0) : x(a), y(b) {}

    // Overloading the + operator
    Point operator + (const Point& p) {
        Point temp;
        temp.x = x + p.x;
        temp.y = y + p.y;
        return temp;
    }

    // Function to display the point
    void display() {
        cout << "(" << x << ", " << y << ")" << endl;
    }
};

int main() {
    Point p1(2, 3);  // Point (2, 3)
    Point p2(4, 5);  // Point (4, 5)

    Point p3 = p1 + p2;  // Adding two points using overloaded + operator

    cout << "Point 1: "; p1.display();
    cout << "Point 2: "; p2.display();
    cout << "Sum of Points: "; p3.display();  // Displays (6, 8)

    return 0;
}

Output:

Point 1: (2, 3)
Point 2: (4, 5)
Sum of Points: (6, 8)

Explanation:

  1. Class Point: Represents a point in a 2D coordinate system with x and y coordinates.
  2. Constructor: Initializes the x and y coordinates of the point. For example, Point(2, 3) creates a point at coordinates (2, 3).
  3. Operator Overloading Function (operator +):
    • This function is used to overload the + operator so it can add two Point objects.
    • Inside the function, the x and y values of the two points are added together, and the result is stored in a temporary object temp, which is then returned.
  4. Display Function: Displays the point in the form (x, y).

4. In main():

  • p1 + p2: This calls the overloaded + operator function. It adds the x and y values of p1 and p2 and returns a new Point object with the result (6, 8).
  • The sum of points is displayed as (6, 8).

Run-Time Polymorphism(Dynamic Binding)

Run-time polymorphism (also known as dynamic polymorphism) is a feature in Object-Oriented Programming (OOP) that allows a program to decide which method to execute at runtime based on the type of object that is invoking the method. It is typically achieved using inheritance and virtual functions.

Virtual Function

Virtual functions are a key feature in Object-Oriented Programming (OOP) that enable run-time polymorphism. They allow derived classes to override functions defined in a base class, and the correct function implementation is selected at runtime based on the actual object type.

For example:

#include <iostream>
using namespace std;

// Base class
class Shape {
public:
    // Virtual function to draw the shape
    virtual void draw() {
        cout << "Drawing a Shape" << endl;
    }
};

// Derived class
class Circle : public Shape {
public:
    // Override the draw function
    void draw() override {
        cout << "Drawing a Circle" << endl;
    }
};

// Another derived class
class Rectangle : public Shape {
public:
    // Override the draw function
    void draw() override {
        cout << "Drawing a Rectangle" << endl;
    }
};

int main() {
    Shape* shapePtr;      // Base class pointer

    Circle circle;        // Derived class object
    Rectangle rectangle; // Another derived class object

    shapePtr = &circle;   // Base class pointer points to Circle object
    shapePtr->draw();     // Calls Circle's draw() method

    shapePtr = &rectangle; // Base class pointer points to Rectangle object
    shapePtr->draw();     // Calls Rectangle's draw() method

    return 0;
}

Output:

Drawing a Circle
Drawing a Rectangle

Explanation:

Step 1: Base Class Shape:

  • Contains a virtual function draw(), which is intended to be overridden by derived classes.
class Shape {
public:
    virtual void draw() {
        cout << "Drawing a Shape" << endl;
    }
};

Step 2: Derived Class Circle:

  • Inherits from Shape and overrides the draw() function.
class Circle : public Shape {
public:
    void draw() override {
        cout << "Drawing a Circle" << endl;
    }
};

Step 3: Derived Class Rectangle:

  • Inherits from Shape and also overrides the draw() function.
class Rectangle : public Shape {
public:
    void draw() override {
        cout << "Drawing a Rectangle" << endl;
    }
};

Step 4: Main Function:

  • Creates a base class pointer shapePtr and assigns it the address of Circle and Rectangle objects one at a time.
  • When shapePtr->draw() is called, the appropriate draw() function is invoked based on the actual object type (Circle or Rectangle), even though shapePtr is a pointer to Shape.
int main() {
    Shape* shapePtr;      // Base class pointer

    Circle circle;        // Derived class object
    Rectangle rectangle; // Another derived class object

    shapePtr = &circle;   // Base class pointer points to Circle object
    shapePtr->draw();     // Calls Circle's draw() method

    shapePtr = &rectangle; // Base class pointer points to Rectangle object
    shapePtr->draw();     // Calls Rectangle's draw() method

    return 0;
}

Summary:

  • Virtual Function: Declared in the base class using the virtual keyword, allowing derived classes to provide their own implementations.
  • Run-Time Polymorphism: The actual function called is determined at runtime based on the type of the object pointed to by the base class pointer.
  • Overriding: Derived classes override the virtual function to provide specific behavior.

    Leave a Reply

    Your email address will not be published.

    Need Help?