Programmers always strive to improve their code—making it simpler, faster, and more reusable. Modern programming languages like C++ have features to help you along. Function overloading is one such feature.

Function overloading allows you to produce more concise and memory-efficient code. Improper use of the feature, however, can cause issues called ambiguities. Read on to learn more about function overloading in C++, including how to use it and how to avoid common pitfalls.

What Is Function Overloading in C++?

For a C++ programmer, function overloading is a powerful tool. It is part of C++ polymorphism, which is the language’s ability to use a function or object in different ways. Function overloading refers to the creation of multiple functions that have different parameters under one name. The compiler determines which function to use by analyzing the parameters (or arguments) that are passed during function call. We call this process overloading resolution.

Benefits of Function Overloading

Function overloading has clear benefits: 

  1. Using a single function name makes your code more readable. Since you have fewer function names to remember, you’re less likely to forget which function does what.
  2. In cases of multiple programmers working on the same program, it helps everyone better comprehend the code: two functions with the same name usually have similar purposes.
  3. Function overloading lets you save memory space. While the effect may be minimal if you’re writing a small application, you’ll notice a significant difference if your program gets large.

How Does Function Overloading Work in C++?

When your compiler faces two or more functions with the same name, it needs a way to differentiate them and call the right one. To do so, it relies on the parameters. 

Parameters in C++

Broadly speaking, a parameter is a factor to consider when making a decision or performing a calculation. When you decide to bake a cake, you consult your cookbook for a recipe. You see that your cake requires a number of eggs—that’s a parameter.

C++ works similarly. Let’s say you’re building a smart home assistant that has a function which buys you eggs from an online store. You would pass the number of eggs as a parameter to the function, letting your program know exactly how many eggs to buy. Here’s how this would work:

#include <iostream>
using namespace std;
// This function expects an int parameter when called
void buyEggs(int nbEggs){ cout << "Okay boss, I am now ordering " << nbEggs << " eggs.";
}

int main(){      // we call the function buyEggs and we pass the parameter 6
buyEggs(6);
return 0;
}

When you call the function buyEggs, the number passed as a parameter is used in the cout object to display a sentence.

The program’s output is as follows:

Okay boss, I am now ordering 6 eggs.

The compiler used the parameter provided in the main() function and passed it to the buyEggs() function.

Implementing Function Overloading 

Parameters are key to function overloading in C++. When the compiler faces two or more functions with the same name, it assesses the parameter types and their order to determine the right function to call. You have three ways of ensuring that the compiler chooses the right function:

  1. Overloading With Different Parameter Types

Let’s return to the code for your smart home assistant and add another layer of complexity. The program is connected to your home’s electrical system and can turn off the lights at your command. You can accomplish this by overloading a function called turnOffLights(). Depending on the data type of the parameter passed (int for the floor or string for the room), the function will perform a different action: 

...//This function takes only an integer as a parameter
void turnOffLights(int houseFloor){
   
// This bit is to formulate a nice looking sentence
string ordinal;
   
switch (houseFloor){
 
    case 1:
    ordinal = "st";
    break;
 
    case 2:
    ordinal = "nd";
    break;
 
    case 3:
    ordinal = "rd";
    break;
 
    default:
    ordinal = "th";
    break;
 
}
   
cout << "Okay boss, I will turn off the lights on the "<< houseFloor
<< ordinal << " floor" << endl;
}// This function works only with a string in inputvoid turnOffLights(string roomName){
   
cout << "Okay boss, I will turn off the lights in the " << roomName << endl;
}...

The first function turnOffLights() takes only an int type parameter. It then confirms that the lights on the selected floor will be turned off. The second function turnOffLights() takes a string parameter and outputs confirmation that the lights in the given room will be turned off.

The main() function calls both functions consecutively:

...int main(){
   
turnOffLights(1);
turnOffLights("Living room");
   
return 0;
}...

We get the following output:

Okay boss, I will turn off the lights on the 1st floor
Okay boss, I will turn off the lights in the Living room

We see that the compiler chose the correct function to call in each instance.

  1. Overloading by Quantity Of Parameters

The compiler can also differentiate overloaded functions by looking at the number of parameters. Let’s say you want your assistant to order food from your favorite Chinese restaurant: 

...//This function takes two int as parameters
void orderChineseFood(int nbAdults, int nbChildren){
   
cout << "Okay boss, I will order " << nbAdults << " adult meals and "
<< nbChildren << " children’s menus." << endl;
}

//This function takes only one int as a parameter
void orderChineseFood(int nbAdults){
   
cout << "Okay boss, I will order " << nbAdults << " adult meals.";
}...

If you only mention a number of people, it assumes there are only adults, but if you specify two different numbers, the program knows you want to order for adults and children. The two functions differ only by the quantity of arguments, as the type is int in both instances:

...int main(){
   
orderChineseFood(2,3);
orderChineseFood(4);
return 0;
}...

The main() function calls both orderChineseFood functions consecutively, passing two different numbers of parameters.

The console outputs the following result:

Okay boss, I will order 2 adult menus and 3 children’s menus.
Okay boss, I will order 4 adult menus.
  1. Overloading With a Different Sequence Of Parameters 

You can also implement function overloading based on differing parameter sequences. Recall our first example of the smart assistant ordering groceries online; this time you want two bananas or a six-count egg carton, or both. Here’s how that would look:

...//This function takes one int and one string
void orderFoodOnline(int nbFood, string nameFood){
   
cout << "Okay boss, I will order " << nbFood << " " << nameFood << endl;

}

//This function takes one string and one int
void orderFoodOnline(string nameFood, int packAmount){
   
cout << "Okay boss, I will order a " << packAmount << " count " << nameFood << " carton.";
   
}...

These two functions are similar, with the only change being their parameter order. Once again, the main() function calls both orderFoodOnline() functions:

...int main(){
   
orderFoodOnline(2,"Bananas");
orderFoodOnline("Eggs",6);
return 0;
}...

And as expected, the compiler gets it right: 

Okay boss, I will order 2 Bananas
Okay boss, I will order a 6 count egg carton

Function Overloading Ambiguities

Function overloading lets your compiler easily determine which function to use. But if your code fails to meet at least one of the three requirements we covered above, the compiler will throw an error called an overloading ambiguity. For example, if you create two functions of the same type, the compiler will not be able to guess the function to use. Here’s what happens when you run the below code, where two functions take the same parameter type:

...
//This function takes only an double as a parameter
void setTemperature(double roomTemperature){
   
cout << "Okay boss, I will set the room temperature to " << roomTemperature << " °F";
}
// This function works only with a double in the input
void setTemperature(double ovenTemperature){
   
cout << "Okay boss, I will set the oven temperature to " << ovenTemperature << " °F";
}

int main(){
   
setTemperature(71.5);
setTemperature(482);
   
return 0;
}

The compiler returns: 

Compilation failed due to following error(s).
main.cpp:19:6: error: redefinition of 'void setTemperature(double)'
void setTemperature(double ovenTemperature){
      ^~~~~~~~~~~~~~
main.cpp:14:6: note: 'void setTemperature(double)' previously defined here
void setTemperature(double roomTemperature){
      ^~~~~~~~~~~~~~

This means that for the compiler, you defined the same function twice. The compiler is unable to tell the difference between the two setTemperature() functions and resolve the overload.

Ambiguities also occur when overloaded functions are called using the default () argument. If an argument is empty when using function overloading, the compiler is unable to tell which function to use.

If you pass a parameter by reference, you will also get an ambiguity error message. Let’s reuse our setTemperature() example to illustrate:

...void setTemperature(double Temperature){
   
cout << "Okay boss, I will set the room temperature to " << Temperature << " °F";
}

void setTemperature(double &Temperature){
   
cout << "Okay boss, I will set the oven temperature to " << Temperature << " °F";
}

int main(){
   
double roomTemperature = 71.5;
setTemperature(roomTemperature);
   
return 0;
}


Once again, the compiler will throw an error:

Compilation failed due to following error(s).

main.cpp:27:35: error: call of overloaded 'setTemperature(double&)' is ambiguous
    setTemperature(roomTemperature);
                                  ^
main.cpp:14:6: note: candidate: void setTemperature(double)
void setTemperature(double Temperature){
      ^~~~~~~~~~~~~~
main.cpp:19:6: note: candidate: void setTemperature(double&)
void setTemperature(double &Temperature){
      ^~~~~~~~~~~~~~


The compiler cannot understand the difference between the two functions, as they’re both valid for the argument that’s passed.

Learn C++ With Udacity

Function overloading is a key programming tool that will make your C++ code cleaner and more efficient. In this article, we showed you how to properly implement function overloading and went over pitfalls to avoid when writing your code.

Interested in continuing your C++ programming journey?

Our specialized C++ nanodegree program will give you the skills you need to code five real-world projects on your own. 

Enroll in our C++ Nanodegree today!

Complete Code Examples

Example 1 : Parameters Explained

#include <iostream>
using namespace std;
//This function expects an int parameter when called
void buyEggs(int nbEggs){

cout << "Okay boss, I am now ordering " << nbEggs << " eggs.";
}

int main(){
      // we call the function buyEggs and we pass the parameter 6
buyEggs(6);
return 0;
}

Example 2: Turn Off The Lights

#include <iostream>
using namespace std;
//This function takes only an integer as a parameter
void turnOffLights(int houseFloor){
   
// This bit is to formulate a nice looking sentence
string ordinal;
   
switch (houseFloor){
 
    case 1:
    ordinal = "st";
    break;
 
    case 2:
    ordinal = "nd";
    break;
 
    case 3:
    ordinal = "rd";
    break;
 
    default:
    ordinal = "th";
    break;
 
}
   
cout << "Okay boss, I will turn off the lights on the "<< houseFloor
<< ordinal << " floor" << endl;
}
// This function works only with a string in input
void turnOffLights(string roomName){
   
cout << "Okay boss, I will turn off the lights in the " << roomName
<< endl;
}
int main(){
   
turnOffLights(1);
turnOffLights("Living room");
   
return 0;
}

Example 3: Order Chinese Food

#include <iostream>
using namespace std;
//This function takes two int as parameters
void orderChineseFood(int nbAdults, int nbChildren){
   
cout << "Okay boss, I will order " << nbAdults << " adult meals and "
<< nbChildren << " children's menus." << endl;
}

//This function takes only one int as a parameter
void orderChineseFood(int nbAdults){
   
cout << "Okay boss, I will order " << nbAdults << " adult meals.";
}
int main(){
   
orderChineseFood(2,3);
orderChineseFood(4);
return 0;
}

Example 4: Order Food Online

#include <iostream>
using namespace std;
//This function takes one int and one string
void orderFoodOnline(int nbFood, string nameFood){
   
cout << "Okay boss, I will order " << nbFood << " " << nameFood << endl;

}

//This function takes one string and one int
void orderFoodOnline(string nameFood, int packAmount){
   
cout << "Okay boss, I will order a " << packAmount << " count " << nameFood << " carton.";
   
}
int main(){
   
orderFoodOnline(2,"Bananas");
orderFoodOnline("Eggs",6);
return 0;
}