![C++ Polymorphism Concepts Explained By C++ Tutors](https://theprogrammingassignmenthelp.com/uploads/blog/2024-02-04-12-20-31ubr6t913yz.jpg)
- 18th Dec 2023
- 22:23 pm
Polymorphism is an important idea in C++ Object-Oriented Programming (OOP). It helps make code flexible, reusable, and easy to add new things to. Coming from Greek words meaning "many" and "shape," polymorphism lets objects show different forms or actions. In C++, there are two main types of polymorphism: one happens when the code is getting ready to run (compile-time), and the other happens while the code is actually running (runtime).
Polymorphism in Compile-Time:
Compile-time polymorphism, often referred to as static or early binding polymorphism, is a distinctive feature in C++. It enables the definition of multiple functions with the same name within a shared scope. This form of polymorphism is resolved during the compilation phase of the program. Compile-time polymorphism is achieved through two basic mechanisms:
-
Function Overloading:
Function overloading allows numerous functions with the same name but distinct parameter lists to be defined.
The compiler differentiates overloaded functions depending on the number, type, or order of arguments.
Example:
```
#include
// Function Overloading
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int main() {
std::cout << add(2, 3) << std::endl; // Calls the int version
std::cout << add(2.5, 3.5) << std::endl; // Calls the double version
return 0;
}
```
-
Operator Overloading:
Operator overloading allows the definition of custom behaviors for operators when applied to objects of user-defined classes.
Operators such as `+`, `-`, `*`, and others can be overloaded.
Example:
```
#include
// Operator Overloading
class Complex {
private:
double real;
double imag;
public:
Complex(double r, double i) : real(r), imag(i) {}
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
void display() const {
std::cout << "Real: " << real << ", Imaginary: " << imag << std::endl;
}
};
int main() {
Complex c1(2.0, 3.0);
Complex c2(1.5, 2.5);
Complex result = c1 + c2; // Calls the overloaded + operator
result.display();
return 0;
}
```
Compile-time polymorphism enhances code readability and expressiveness, allowing developers to create versatile and intuitive interfaces within their programs.
Runtime Polymorphism:
Runtime polymorphism, often known as dynamic or late binding polymorphism, is an important element of C++ Object-Oriented Programming (OOP). It enables objects to behave differently during program execution based on their real-derived types. Virtual functions and pointers or references to base class objects are used to achieve runtime polymorphism.
-
Virtual Functions:
A virtual function is a member function that is declared in a base class and is denoted with the 'virtual' keyword.
It is meant for derived classes to override, allowing them to provide their own implementations.
Example:
```
#include
// Base class with a virtual function
class Shape {
public:
virtual void draw() const {
std::cout << "Drawing a shape." << std::endl;
}
};
// Derived class overriding the virtual function
class Circle : public Shape {
public:
void draw() const override {
std::cout << "Drawing a circle." << std::endl;
}
};
int main() {
Shape* shapePtr = new Circle(); // Pointer to base class pointing to a derived class object
shapePtr->draw(); // Calls the overridden draw() of Circle
delete shapePtr;
return 0;
}
```
-
Pointers or References to Base Class:
Derivative class objects can be handled as pointers or references to their base class, allowing for dynamic method binding. This provides flexibility in selecting the proper method implementation based on the actual type of the object during runtime.
Example:
```
#include
// Base class with a virtual function
class Animal {
public:
virtual void sound() const {
std::cout << "Generic animal sound." << std::endl;
}
};
// Derived classes overriding the virtual function
class Dog : public Animal {
public:
void sound() const override {
std::cout << "Bark! Bark!" << std::endl;
}
};
class Cat : public Animal {
public:
void sound() const override {
std::cout << "Meow! Meow!" << std::endl;
}
};
int main() {
Animal* animalPtr = new Dog(); // Pointer to base class pointing to a derived class object
animalPtr->sound(); // Calls the overridden sound() of Dog
delete animalPtr;
return 0;
}
```
Runtime polymorphism is a strong idea that enables more dynamic and adaptable programming, particularly in situations when the actual type of objects varies during program execution. It helps C++ applications to be more flexible and maintainable.
Compile-time polymorphism (function overloading) and runtime polymorphism (virtual functions) are used in this C++ program:
```
#include
// Base class with virtual functions
class Shape {
public:
// Virtual function to be overridden by derived classes
virtual void draw() const {
std::cout << "Drawing a shape." << std::endl;
}
};
// Derived class overriding the virtual function
class Circle : public Shape {
public:
void draw() const override {
std::cout << "Drawing a circle." << std::endl;
}
};
// Function with compile-time polymorphism (function overloading)
void drawShape(const Shape& shape) {
shape.draw(); // Calls the appropriate draw() based on the actual object type
}
int main() {
// Using runtime polymorphism
Shape* shapePtr = new Circle(); // Pointer to base class pointing to a derived class object
shapePtr->draw(); // Calls the overridden draw() of Circle
// Using compile-time polymorphism
Shape rectangle; // Creating an object of the base class
Circle circle; // Creating an object of the derived class
drawShape(rectangle); // Calls the draw() for Shape
drawShape(circle); // Calls the draw() for Circle
delete shapePtr;
return 0;
}
```
Explanation:
- The 'Shape' class provides a virtual function 'draw()' that descendant classes can override.
- The 'Circle' class derives from 'Shape' and implements the 'draw()' function on its own.
- The function 'drawShape' exhibits compile-time polymorphism. It accepts a 'Shape' reference and calls the 'draw()' method. The proper version of 'draw()' is chosen based on the kind of object given.
- We employ runtime polymorphism in the 'main' method by constructing a reference to a 'Shape' that points to a 'Circle' object. The virtual method 'draw()' is called on this pointer, which causes the overridden function in the 'Circle' class to be executed.
- This program creates objects for both the main class 'Shape' and the special class 'Circle'. Then, it uses the 'drawShape' method on them, showing compile-time polymorphism.
In simple terms, this program shows how C++ can pick the right action when it's running and also depending on the types when it's getting ready to run.
About the Author - Jane Austin
Jane Austin is a 24-year-old programmer specializing in Java and Python. With a strong foundation in these programming languages, her experience includes working on diverse projects that demonstrate her adaptability and proficiency in creating robust and scalable software systems. Jane is passionate about leveraging technology to address complex challenges and is continuously expanding her knowledge to stay updated with the latest advancements in the field of programming and software development.