In object-oriented programming, two important concepts that play a significant role in designing and implementing classes and functions are function overloading and function overriding. Both of these concepts provide ways to achieve polymorphism, which is the ability of objects of different classes to be treated as objects of a common base class. In C++, function overloading and function overriding are powerful tools that allow us to write more flexible and reusable code.
In this answer, we will delve into the differences between function overloading and function overriding, providing code examples to explain each concept.
Function overloading refers to the practice of defining multiple functions in the same scope with the same name but different parameter lists. The compiler differentiates between these functions based on the number or types of arguments they accept. This allows us to provide various ways to call a function depending on the program’s specific requirements.
Let’s consider a simple example of function overloading:
#include <iostream>using namespace std;class MathOperations {public:int add(int a, int b) {return a + b;}double add(double a, double b) {return a + b;}};int main() {MathOperations math;cout << math.add(2, 3) << std::endl; // Calls the int version of addcout << math.add(2.5, 3.7) << std::endl; // Calls the double version of addreturn 0;}
In this example, the MathOperations
class defines two add
functions—one that accepts int
parameters and another that accepts double
parameters. The correct version of the function is called based on the argument types provided.
Let’s go over the code in detail:
Line 5: We define a class named MathOperations
.
Lines 7–9: We define a function, add
, that calculates the sum of two integers and returns the result as an integer.
Lines 11–13: We define another function with the same name, add
, but this one calculates the sum of two double
parameters and returns the result as a double
.
Line 17: Inside the main
function, we create an instance of the MathOperations
class named math
.
Line 19: We call the add
function with integer arguments 2
and 3
. It calls the int add(int a, int b)
version of the function. The result is then printed to the console.
Line 20: Similarly, we call the add
function with double arguments 2.5
and 3.7
. It calls the double add(double a, double b)
version of the function. The result is then printed to the console.
Function overriding, on the other hand, occurs in the context of inheritance, and it allows a subclass to provide a specific implementation for a method that is already defined in its base class. In other words, the subclass can override the behavior of the method inherited from the base class.
Consider the following example:
#include <iostream>using namespace std;class Shape {public:virtual void draw() {cout << "Drawing a shape." << std::endl;}};class Circle : public Shape {public:void draw() override {cout << "Drawing a circle." << std::endl;}};int main() {Shape* shapePtr = new Circle;shapePtr->draw(); // Calls the overridden draw method in Circledelete shapePtr;return 0;}
In this example, we have a base class Shape
with a virtual function draw()
. The derived class Circle
overrides the draw()
method to provide its own implementation. When a Circle
object is accessed through a pointer to a Shape
, the overridden version of the function in the Circle
class is called.
Let’s go over the code in detail:
Line 5: We define the base class named Shape
.
Lines 7–9: We create a virtual function, draw
, in the base class Shape
. The virtual
keyword indicates that this function can be overridden by derived classes. This function prints the message "Drawing a shape."
to the console.
Line 12: We define the derived class named Circle
that inherits publicly from the Shape
class.
Lines 14–16: We define the overridden draw
function in the Circle
class. The override
keyword explicitly indicates that this function is intended to override the base class’s virtual function. This function prints the message "Drawing a circle."
to the console.
Line 20: Inside the main
function, we create a pointer shapePtr
of type Shape*
and assign it the address of a newly created Circle
object. This is a demonstration of polymorphism, as a Circle
object is being treated as a Shape
.
Line 21: We call the draw
method through the shapePtr
. Since the shapePtr
points to a Circle
object, the overridden version of the draw
function in the Circle
class is called, resulting in "Drawing a circle."
being printed.
Line 23: We deallocate the memory occupied by the dynamically allocated Circle
object.
Function overloading | Function overriding | |
Context | Provides multiple implementations of a function with the same name but different parameter lists in the same class | Provides a specialized implementation of a method in a derived class that has been defined in the base class |
Scope | Occurs within the same class | Occurs in a derived class that inherits from a base class |
Usage | Provides different ways to call a function with varying parameters | Provides specialized behavior in derived classes that extends or modifies the behavior of the base class |
Polymorphism | Achieves compile-time polymorphism (also known as static polymorphism) | Achieves runtime polymorphism (also known as dynamic polymorphism) through virtual functions |
Free Resources