Welcome to our guide on Polymorphism In C++ and its various types.
If you’re wondering, “What is Polymorphism in C++?” or seeking to explore the complexity of this powerful concept, you’re in the right place.
In this blog, we delve into the fundamentals of Polymorphism in C++ and explain how it allows for versatility and efficiency in programming.
From virtual functions to differences between runtime and compile-time, we’ll break down key techniques with Polymorphism in C++ examples that enable you to write adaptable and reusable code.
Whether you’re just starting or a professional programmer, this blog is your go-to resource for mastering Polymorphism in C++.
Join our “Introduction to C++” course and build a strong foundation in programming that will serve you throughout your career!
Define Polymorphism In C++?
Polymorphism in C++ refers to the ability of objects to take on multiple forms based on their context or usage. It allows different objects to respond to the same message differently.
Like real-life scenarios where a person can exhibit various roles simultaneously, such as being a parent, spouse, and employee, C++ Polymorphism enables objects to exhibit different behaviors depending on the situation.
This feature is integral to Object-Oriented Programming and enhances code flexibility and reusability.
Explore a variety of “C++ Projects To Work On In 2024” and find the perfect project to showcase your skills.
Types of polymorphism In C++
In C++, two primary types of Polymorphism are:
- Compile-Time Polymorphism
- Runtime Polymorphism
Now, let’s delve deeper into these types of Polymorphism in C++ and explore how they contribute to flexibility and extensibility.
1. Compile Time Polymorphism
Compile-time Polymorphism refers to the mechanism in C++ where the compiler determines which function to call during compilation based on the function’s signature and the context in which it is invoked. This is typically achieved through function overloading and operator overloading.
A. Function Overloading
Function overloading occurs when multiple functions have the same name but different parameters.
This enables the same function name to perform various tasks based on the parameters provided, which can vary in number or type.
It’s a feature of object-oriented programming that allows for creating multiple functions with the same name but different parameter lists.
Here’s an example of function overloading in C++:
#include <iostream>
using namespace std;
class Overload {
public:
void print(int num) {
cout << "Printing integer: " << num << endl;
}
void print(double num) {
cout << "Printing double: " << num << endl;
}
void print(string text) {
cout << "Printing string: " << text << endl;
}
};
int main() {
Overload obj;
obj.print(5);
obj.print(10.5);
obj.print("Hello World");
return 0;
}
Output
Printing integer: 5
Printing double: 10.5
Printing string: Hello World
Explaination
In this example, the ‘Overload
class‘ demonstrates function overloading. It contains three ‘print
‘ functions, each with a different parameter type (int, double, string).
When the '
function is called with different arguments, the appropriate version of the function is invoked based on the parameter type. print
This demonstrates compile-time Polymorphism, as the decision of which function to call is made by the compiler at compile time based on the function’s signature.
B. Operator Overloading
In C++, operator overloading empowers operators to have special meanings for specific data types. For instance, we can redefine the addition operator (+) for the string class to concatenate two strings. This flexibility allows us to extend the functionality of operators beyond their conventional usage.
Here’s an example showcasing operator overloading in C++:
#include <iostream>
#include <string>
using namespace std;
class StringConcat {
private:
string str;
public:
StringConcat() : str("") {}
StringConcat(string s) : str(s) {}
StringConcat operator+(const StringConcat& obj) {
StringConcat result;
result.str = this->str + obj.str;
return result;
}
void display() {
cout << "Concatenated String: " << str << endl;
}
};
int main() {
StringConcat str1("Hello");
StringConcat str2("World");
StringConcat result = str1 + str2;
result.display();
return 0;
}
Output
Concatenated String: HelloWorld
Explanation
This code snippet defines a ‘StringConcat’ class with a member variable str of type string. We then overload the addition operator + inside the class.
When two ‘StringConcat’ objects are added using the + operator, the overloaded operator function is invoked, which concatenates the string members of both objects.
Finally, the concatenated string is displayed. This illustrates how operator overloading in C++ enables us to redefine the behavior of operators for custom data types, providing greater flexibility and readability in code.
Need More clarity on operator overloading in C++?
Explore our guide: “Operator Overloading in C++ with Examples | 2024“
2. Runtime Polymorphism
Runtime Polymorphism in C++, also known as late binding or dynamic Polymorphism, is achieved through function overriding.
Unlike compile-time Polymorphism, where the function call is resolved at compile time, run time Polymorphism in C++ resolves the function call at runtime.
This allows for greater flexibility as the specific function implementation is determined based on the actual object type during program execution.
A. Function overriding
Function overriding occurs when a derived class provides a specific implementation for a function already defined in its base class. This allows objects of the derived class to use their version of the function, providing a way to achieve runtime Polymorphism.
Here’s an example demonstrating function overriding in C++ related to car colors:
#include <iostream>
#include <string>
using namespace std;
class Car {
public:
virtual void displayColor() {
cout << "The car is colored in default color." << endl;
}
};
class RedCar : public Car {
public:
void displayColor() override {
cout << "The car is colored red." << endl;
}
};
class BlueCar : public Car {
public:
void displayColor() override {
cout << "The car is colored blue." << endl;
}
};
int main() {
Car* car1 = new RedCar();
Car* car2 = new BlueCar();
car1->displayColor();
car2->displayColor();
delete car1;
delete car2;
return 0;
}
Output
The car is colored red.
The car is colored blue.
Explanation
This code has a base class Car with a virtual function ‘displayColor()’. Two derived classes, RedCar and BlueCar, override this function to provide their implementations of displaying the car color.
In the main() function, we create pointers to objects of type Car pointing to instances of RedCar and BlueCar. When calling the displayColor() function through these pointers, the appropriate overridden version of the function is invoked based on the actual object type, demonstrating runtime Polymorphism.
Also, read “Function Overloading in C++ With Examples – 2024” to learn how to create cleaner and more readable C++ code!
B. Virtual Function
A virtual function is a member function declared within a base class that is redefined (or overridden) in a derived class. It allows the derived class to provide its implementation of the function, which is invoked based on the actual object type during runtime.
This enables runtime Polymorphism, where the appropriate function implementation is selected dynamically based on the object’s type rather than statically at compile time.
Key Points To Remember:
- Virtual functions are declared using the virtual keyword in the base class.
- They are overridden in derived classes using the override keyword.
- Virtual functions enable dynamic binding, where the call is resolved at runtime.
- They allow for polymorphic behavior, where objects of different derived classes can be treated uniformly through a standard interface.
Example: Car Brands
#include <iostream>
#include <string>
using namespace std;
class Car {
public:
virtual void displayBrand() {
cout << "This is a generic car." << endl;
}
};
class Ford : public Car {
public:
void displayBrand() override {
cout << "This is a Ford car." << endl;
}
};
class Toyota : public Car {
public:
void displayBrand() override {
cout << "This is a Toyota car." << endl;
}
};
int main() {
Car* car1 = new Ford();
Car* car2 = new Toyota();
car1->displayBrand();
car2->displayBrand();
delete car1;
delete car2;
return 0;
}
Output
This is a Ford car.
This is a Toyota car.
Explanation
In this example, we have a base class Car with a virtual function ‘displayBrand()‘. Two derived classes, Ford and Toyota, override this function to provide their implementations of displaying the car brand.
We create pointers for objects of type, pointing to instances of Ford and Toyota in the ‘main()‘ function. When calling the ‘displayBrand()‘ function through these pointers, the appropriate overridden version of the function is invoked based on the actual object type, demonstrating runtime Polymorphism.
Difference Between Runtime & Compile-Time
Feature | Compile-Time Polymorphism | Runtime Polymorphism |
Definition | Compile time Polymorphism in C++ determines which function or operation to call based on the number, types, and order of arguments. | The decision of which function to call is determined at runtime based on the actual object type rather than the reference or pointer type. |
Binding | Static binding, where the function calls are statically bound to their definitions. | Dynamic binding, where the function calls are dynamically bound to their definitions. |
Polymorphism Type | Compile-time Polymorphism, also known as static or early binding Polymorphism. | Runtime Polymorphism, also known as late binding or dynamic Polymorphism. |
Function Overloading | Multiple functions have the same name but different parameters defined. The compiler determines which function to call based on the number and types of arguments. | Not applicable. |
Operator | Overloading Operators can be overloaded to perform different operations based on the types of operands. | Not applicable. |
Inheritance | Not involved. | Involves inheritance, where a derived class overrides a function from its base class. |
Execution Speed | Faster execution rate, as the compiler determines which function to call at compile-time. | Comparatively slower execution rate, as the decision of which function to call is made at runtime. |
Code Reusability | High code reusability, as the same function name can be used with different parameters. | High code reusability, as the same function name can be used with different object types. |
Polymorphism In C++ | Compile-time Polymorphism is achieved by function overloading of operator overloading. | Runtime Polymorphism is achieved by function overriding. |
Also don’t miss out on our guide on “Templates in C++ With Examples | 2024“
Wrapping Up
We hope this comprehensive guide on Polymorphism C++ has provided you with a clear understanding of this fundamental concept.
You’ve explored various techniques to enhance code flexibility and reusability from compile-time Polymorphism achieved through function and operator overloading to runtime Polymorphism facilitated by function overriding and virtual functions.
If you’re enthusiastic about expanding your knowledge and expertise into C++ OR software engineering, consider exploring Great Learning’s free C++ tutorial and software engineering courses.
Our resources offer a structured path from understanding Polymorphism in C++ to mastering advanced concepts, providing invaluable skills for aspiring software engineers.
Don’t miss out on the opportunity to accelerate your learning journey and unlock new possibilities in the programming world.
FAQs
Yes, polymorphism can be achieved without inheritance in C++ using interfaces or abstract classes. Interfaces define a set of methods that derived classes must implement, enabling polymorphic behavior without needing a standard base class.
One limitation of polymorphism in C++ is the overhead associated with virtual function calls, which can impact performance in performance-critical applications. Polymorphism relies on inheritance, which may lead to tight coupling between classes if not used carefully.
Some best practices for using polymorphism in C++ include:
– Designing a clear and cohesive class hierarchy.
– Favoring composition over inheritance when possible.
– Using virtual functions judiciously to avoid unnecessary overhead.
Additionally, adhering to naming conventions and documenting class interfaces can improve code readability and maintainability.
Yes, polymorphism can be achieved with non-member functions in C++ by using function templates. Function templates allow you to define a single function that can operate on different data types, providing a form of compile-time polymorphism similar to function overloading but applicable to non-member functions.
Many online resources, including textbooks, tutorials, and courses, are available for learning about advanced C++ polymorphism concepts.
Platforms like Great Learning offer comprehensive courses on C++ programming, covering topics such as polymorphism, an an example of polymorphism in C++C++, inheritance, and and advanced object-oriented programming techniques.
Participating in C++ programming communities and forums can provide valuable insights and guidance from experienced developers.