Function overloading is a feature of having multiple functions with same name but different input parameters. The input parameters of the overloaded functions should be different in some way. Either the data types of the input parameters could be different or the number of input parameters could be different. This is one of the important features in C++.
In many programming languages like C, we don’t have this feature – can’t have more than one function with same name.
We can overload the normal standalone functions as well as class constructors and member functions.
Function Overloading by Input Parameter Data Type Difference
#include <iostream>
using namespace std;
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
string add(string a, string b) {
return a + b;
}
int main() {
cout << add(4, 5) << endl;
cout << add(4.3, 5.2) << endl;
cout << add("QnA ", "Plus") << endl;
return 0;
}
$ g++ -o test test.cpp
$ ./test
9
9.5
QnA Plus
In this example, we have three functions with the same name, add. All three functions have two input parameters. The data types of these input parameters are different in each function.
In main(), we called the add() function thrice.
In the first call, we provided two integers, 4 and 5, as input. The compiler figured out the correct version of the overloaded functions – the first one with produced 9 as output.
Similarly, in the second call we provided two doubles as input. This resulted the call of the second version of the overloaded function and produced the double summation 9.5 as the result.
In the third call, we provided two string inputs. So, the third overloaded function was called and the concatenation of the two input strings was produced as result.
Note: we can have overloaded functions with same number of arguments with mix data types. The sequence of the data types should not match though.
We can have overloaded functions like this:
double add(double a, int b) {
return a + b;
}
double add(int a, double b) {
return a + b;
}
Function Overloading by Different Number of Input Parameters
#include <iostream>
using namespace std;
int add(int a, int b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
int main() {
cout << add(4, 5) << endl;
cout << add(4, 5, 6) << endl;
return 0;
}
$ ./test
9
15
In this example, the first add() function has two input parameters while the second one has three.
In main(), first we called the add() function with 2 inputs and then with 3 inputs. The compiler figured out the correct over loaded functions to call in each case.
Benefits
- It improves code readability and elegance. Without this feature, we need to invent many function names for the same purpose – like, add_int(), add_double(), add_string() etc. It reduces the code elegance and is cumbersome also.
- It facilitate one of the most importance OOP features – polymorphism.
Ambiguity
When a function is called, the compiler tries to figure out the best possible match from the overloaded functions. If it finds multiple matches and can not decide which one to call, it generates compilation error.
Type Conversion Related Ambiguity
#include <iostream>
using namespace std;
float add(int a, int b) {
return a + b;
}
float add(float a, float b) {
return a + b;
}
int main() {
cout << add(4.1, 5.1) << endl;
return 0;
}
This program does not compile.
$ g++ -o test test.cpp
test.cpp: In function ‘int main()’:
test.cpp:13:16: error: call of overloaded ‘add(double, double)’ is ambiguous
13 | cout << add(4.1, 5.1) << endl;
| ~~~^~~~~~~~~~
You might have expected that the float version of the version should have been called. But in C++, floating pointing literals are treated as double unless specified otherwise. As we don’t have double version of this function, compiler will not be able to decide whether to convert the double into int or float.
There are several ways to solve this problem.
We can tell the compiler that the input constants are not doubles but floats.
cout << add(4.1f, 5.1f) << endl;
We can pass float type variables instead of the constants.
float a = 4.1, b = 5.1;
cout << add(a, b) << endl;
Another way is to have only one number version of the functions – even if we have the int version.
#include <iostream>
using namespace std;
float add(int a, int b) {
return a + b;
}
string add(string a, string b) {
return a + b;
}
int main() {
cout << add(4.1, 5.1) << endl;
return 0;
}
If we have only the int version, then we’ll not get the floating point level precision. So, the result of this addition here will be 9, not 9.2.
Default Argument Related Ambiguity
#include <iostream>
using namespace std;
float add(int a, int b) {
return a + b;
}
float add(int a, int b, int c = 0) {
return a + b + c;
}
int main() {
cout << add(4, 5, 6) << endl;
cout << add(4, 5) << endl;
return 0;
}
Here we have two input arguments in the first add() function and three in the second one. But in the second function, third parameter is optional. That means the second function can be called both with two or three parameters.
If we call this function with 3 parameters, there is no confusion. But if we try to call with two parameters, the compiler will have two choices. And there is no other way to resolve that. So, it will produce compilation error.
$ g++ -o test test.cpp
test.cpp: In function ‘int main()’:
test.cpp:14:16: error: call of overloaded ‘add(int, int)’ is ambiguous
14 | cout << add(4, 5) << endl;
Pass by Reference Related Ambiguity
#include <iostream>
using namespace std;
void print(int x) {
cout << x << endl;
}
void print(int& x) {
cout << x << endl;
}
int main() {
int x = 5;
print(5);
print(x);
return 0;
}
Here we have two print() functions. First one has an int type input and the second one has an int reference type input.
If we can this function with an int constant like 5, there is no problem. The r-value constant can not be converted into a reference. So, the first version of the print() function will be called.
But if we call this function with an int variable, then the compiler will have two choices. The print() function can be called by value or reference. So, the compiler will produce ambiguity error.
$ g++ -o test test.cpp
test.cpp: In function ‘int main()’:
test.cpp:17:10: error: call of overloaded ‘print(int&)’ is ambiguous
17 | print(x);
| ~~~~~^~~