Function overloading in C++ allows us having multiple definitions of a single function or method. That means that we can have multiple functions with same name. But their input arguments need to be different, either in data type or number of arguments. In time of calling the function, the compiler decides which function to call based on the arguments passed.
Function Overloading using Type Difference
If multiple functions with same name has same number of arguments, data type of at least one argument needs to be different.
void print(int arg) {
std::cout << "Printing int value: " << arg << std::endl;
}
void print(double arg) {
std::cout << "Printing double value: " << arg << std::endl;
}
Above two functions have the same name and same number of arguments. But the argument type is different, one is int, another is double.
We can call this functions like this.
int main(){
print(5);
print(5.6);
return 0;
}
First we called the print() function with an integer (int) value 5. Compiler will select the first print() function as the first function takes integer (int) as input. Similarly, when we called the function with a double value 5.6, the compiler will select the second function.
Here is the output of the program.
Printing int value: 5
Printing double value: 5.6
Function Overloading with Different Number of Arguments
We can have functions with same name if the functions have different number of arguments. Data types of the arguments can be same. Here is the example of such overloading.
void sum(int a, int b) {
std::cout << "Sum of two integers: " << (a+b) << std::endl;
}
void sum(int a, int b, int c) {
std::cout << "Sum of three integers: " << (a+b+c) << std::endl;
}
The first function has two arguments but the second one has three. We can call these functions like this.
sum(1, 2);
sum(1, 2, 3);
Here is the output.
Sum of two integers: 3
Sum of three integers: 6
Ambiguity
You can define overloaded functions by having parameters of different type or number. But when we call such function, compiler might get confused on which function to call. Ambiguity can arise from various reasons.
- Internal type conversion.
- Usage of optional parameter.
- Usage of reference type parameter.
Ambiguity for Internal Type Conversion
Lets consider this overload function.
void print(int arg) {
std::cout << "Printing int value: " << arg << std::endl;
}
void print(float arg) {
std::cout << "Printing float value: " << arg << std::endl;
}
We can call this print() function like this.
int main(){
int a = 2;
float b = 2.3;
print(a);
print(b);
return 0;
}
Here is the output.
Printing int value: 2
Printing float value: 2.3
Quite obviously the first print() function is called for integer type variable a, and the second one is called for float type variable b.
Now lets change the program little bit like this.
int main(){
print(2);
print(2.3);
return 0;
}
This is quite similar to the above program and you might expect the same output. But this program will produce compilation error.
In function 'int main()':
prog.cc:14:12: error: call of overloaded 'print(double)' is ambiguous
14 | print(2.3);
| ^
prog.cc:3:6: note: candidate: 'void print(int)'
3 | void print(int arg) {
| ^~~~~
prog.cc:7:6: note: candidate: 'void print(float)'
7 | void print(float arg) {
| ^~~~~
Here the compiler got confused to decide which function to use for print(2.3) call. You might think this is obvious. As 2.3 is a float type variable, the second print() function should be called.
But in C++, a floating constant is considered as of double type. But there is no print() function that takes double type input. So the compiler use internal type conversion to find appropriate match. Now a double can be converted to both float and int. So the compiler confused which one to choose.
Ambiguity for Usage of Optional Parameter.
Lets consider this overloaded function.
void sum(int a, int b) {
std::cout << "Sum of two integers: " << (a+b) << std::endl;
}
void sum(int a, int b, int c = 0) {
std::cout << "Sum of three integers: " << (a+b+c) << std::endl;
}
Number of parameters of these two functions is different but the third parameter of the second function is optional. The second function can take both two or three parameters. If we call sum() with three parameters there is no ambiguity.
sum(1, 2, 3);
If we call this function like above, there is no problem. But if we try to call with two parameters like this:
sum(1, 2);
Compiler gets confused. Because both the functions can be called with two parameters. If we try to run the program, we’ll get errors like this.
error: call of overloaded 'sum(int, int)' is ambiguous
13 | sum(1, 2);
| ^
prog.cc:3:6: note: candidate: 'void sum(int, int)'
3 | void sum(int a, int b) {
| ^~~
prog.cc:7:6: note: candidate: 'void sum(int, int, int)'
7 | void sum(int a, int b, int c = 0) {
| ^~~
Ambiguity for Usage of Reference
If we use reference and non-reference type input parameters, sometimes compiler gets confused. Lets consider this overloaded function.
void display(int i) {
std::cout << "Input integer: " << i << std::endl;
}
void display(int& i) {
std::cout << "Input integer (using reference): " << i << std::endl;
}
First version of the function takes an integer as input and second version takes integer reference as input.
We can call this function using an integer constant like this.
display(5);
Here there is no confusion. The compiler will select the first version of the function. But if we try to call this same function using an integer variable, then confusion arises.
int x = 5;
display(x);
Now both the functions can be called with the integer variable x. In this situation the compiler will throw errors like this.
prog.cc:13:12: error: call of overloaded 'display(int&)' is ambiguous
13 | display(x);
| ^
prog.cc:3:6: note: candidate: 'void display(int)'
3 | void display(int i) {
| ^~~~~~~
prog.cc:7:6: note: candidate: 'void display(int&)'
7 | void display(int& i) {
| ^~~~~~~