Why we actually need runtime polymorphism?
Asked Answered
C

4

6

I'm trying to understand a polymorphism but I don't understand why we need runtime polymorphism if static polymorphism works fine for calling members of a class.

Like, suppose this was a problem.

#include <bits/stdc++.h>
using namespace std;
class base{
    public:
        virtual void fun(){
            cout<<"base called"<<endl;
        }
};
class derived:public base{
    public:
        void fun(){
            cout<<"derived called"<<endl;
        }
};
int main() {

    base b,*b1;
    derived d;
    b1 = &d;
    b1->fun();
    // b.fun();
    // d.fun();
}

suppose this was my code and I want to access the function of derived or base class and I was able to do it by simply creating an object of that class so if there is no problem then why we try to call the object using references (runtime polymorphism). Can someone explain the actual need for runtime polymorphism or if it is possible can you explain it by using any real-life scenarios??

Cordite answered 31/5, 2020 at 7:47 Comment(3)
I hope this helps: #14953722Glottic
Why should I not #include <bits/stdc++.h>?Teenyweeny
Look at void f(base* b) { b->fun(); }. Which function does it call?Sussi
V
3

Polymorphism is useful any time that the software can't be told at compile time exactly what everything is going to be at runtime, or when you need a container to be able to hold a heterogeneous assortment of things that all implement a common interface.

A good example is UI toolkits. Pretty much all UI toolkits have a concept of a container that can hold other widgets, but the UI toolkit author has no idea what widgets you are going to put into the container. Since the container needs to be able to deal with any kind of widget, polymorphism is the easiest way to achieve this.

Visigoth answered 31/5, 2020 at 8:37 Comment(0)
E
4

Polymorphism is considered as one of the important features of Object-Oriented Programming. In C++ polymorphism is mainly divided into two types:

  • Compile-time Polymorphism: This type of polymorphism is achieved by function overloading or operator overloading.

  • Runtime Polymorphism: This type of polymorphism is achieved by Function Overriding.

Now consider the following scenario.

Suppose we have a base class named Shape which has the following interface.

class Shape {
public:
    Shape(int init_x, int init_y);
    virtual ~Shape() = default;

    virtual void scale(int s) = 0;
protected:
    int x;
    int y;
};

Now we want to inherit two other classes named Rectangle and Circle from it.

class Rectangle : public Shape {
public:
    Rectangle(int init_x, int init_y, int w, int h);
    void scale(int s) override;
private:
    int width;
    int height;
};
class Circle : public Shape {
public:
    Circle(int init_x, int init_y, int r);
    void scale(int s) override;
private:
    int radius;
};

As you may know, circle and rectangle shapes, have different implementation for their scale method, so I can't implement that in the Shape class.

Now suppose we have a program that stores all the shapes in a container like vector<Shape*> (e.g. it gets all the shapes from the user once and store them in this container).

If we want to use scale method on one of the shapes, we don't know actually which kind of shape we are dealing with, but it will bind our scale method call to its appropriate implementation.

Euphonic answered 31/5, 2020 at 9:39 Comment(3)
I'm pretty much got your point but as you say that "we don't know actually which kind of shape we are dealing with" so why we are doing this step for calling a function of particular derived class. ` base b,*b1; derived d; b1 = &d; // this step basically`Cordite
@ShivamJain Suppose you have some other classes like Rectangle and Circle (e.g. Square, Triangle and etc.). If you do not want to collect them all in one container (e.g. vector<Shape*>), you have to have multiple containers that each of them contains a specific type of shape. Actually polymorphism adds a level of abstraction in your design which is one of the most important principles to have a good design.Euphonic
I recommend using void scale(int s) override; in the derived classes instead of virtual void scale(int s);.to get a compile-time error if it doesn't override a virtual method as it's supposed to do and I made that change to the answer. I also added a virtual destructor to the base class so you can delete objects through a base class pointer.Natch
V
3

Polymorphism is useful any time that the software can't be told at compile time exactly what everything is going to be at runtime, or when you need a container to be able to hold a heterogeneous assortment of things that all implement a common interface.

A good example is UI toolkits. Pretty much all UI toolkits have a concept of a container that can hold other widgets, but the UI toolkit author has no idea what widgets you are going to put into the container. Since the container needs to be able to deal with any kind of widget, polymorphism is the easiest way to achieve this.

Visigoth answered 31/5, 2020 at 8:37 Comment(0)
B
2

Suppose you have a library which has a class and few methods which takes a pointer to that class.

class GameObject {
public:
    virtual void paint(void);

public:
    void print_to_display(void);

};

class Game {

public:
    void add_obj(GameObject *obj);
};

Since, you just have the library (shared library and few header files) and you don't want to modify the libraries source code (as it may break existing method).

You can extend the class GameObject in your project and override it's print method to do something other than the default behavior.

class MyObject: public GameObject {

public:
    void paint(void) override;
};
Biconcave answered 31/5, 2020 at 7:56 Comment(1)
which paint function are you overriding even?Settlings
G
0

@cdhowie has perfectly explained this. Just adding another example.

Without runtime-polymorphism, overriding a function in C++ is like an incomplete recipe. In such a case, the derived class function will mask or hide inside the base class instead of overriding it.

Suppose, Class A implements function_1 and function_2. Also, function_1 calls function_2. Now class B inherits Class A and re-implements function_2. What will happen when an instance of Class B calls function_1? Will it call class A's or class B's function_2?

Consider the following code:

#include<bits/stdc++.h>

class A {
public:
  void function_1() {
    std::cout << "This is function_1 from Class A\n";
    this->function_2();
  }

  void function_2() {
    std::cout << "This is function_2 from Class A\n";
  }
};

class B : public A {
public:
  void function_2() {
    std::cout << "This is function_2 from Class B\n";
  }
};

int main() {
  B b;
  b.function_1();
  b.function_2();
  return 0;
}

Output:

This is function_1 from Class A
This is function_2 from Class A
This is function_2 from Class B

The only way we can call function_2 of class B from function_1 of class A is by using virtual functions

#include<bits/stdc++.h>
using namespace std;

class A {
public:
  void function_1() {
    std::cout << "This is function_1 from Class A\n";
    this->function_2();
  }

  virtual void function_2() {
    std::cout << "This is function_2 from Class A\n";
  }
};

class B : public A {
public:
  virtual void function_2() {
    std::cout << "This is function_2 from Class B\n";
  }
};

int main() {
  B b;
  b.function_1();
  b.function_2();
  return 0;
}

Output

This is function_1 from Class A
This is function_2 from Class B
This is function_2 from Class B
Godred answered 13/4, 2023 at 15:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.