Function Overloading
In some languages, like C or Python, a function’s name has to be unique. Suppose you already have a function power that takes a base and an exponent and raises one to the other (like ). Now you need a separate version with integer parameters, but the name power is already taken, so you end up with something like powerInt, two names for the same idea.
C++ drops this restriction. You can give two functions the same name, as long as their parameters are different enough for the compiler to tell them apart. This is called function overloading. It’s useful when the two versions of a function genuinely need different logic, and it lets both versions share one intuitive name.
Overloaded functions: Same name, different jobs
Same name, different logic
C++ already has a pow function, in the <cmath> header file, but it’s built for decimals. Using it for whole numbers comes with a catch. A call like std::pow(10, 2) can return 99.99999999999999 instead of exactly 100. This rounds to 100 when printed, but if stored in a variable of type int, it truncates to 99, a full one off from the right answer.
For whole numbers, using a plain loop is less risky, and it’s also cheaper in terms of time taken:
Both functions are named power, but their implementations are different:
- The
intversion (lines 4–10) repeatedly multiplies bybase, working entirely with integers, so the result is exact. - The
doubleversion (lines 12–14) leans onstd::pow, which is built to handle fractional exponents (like0.5for a square root).
The two calls to power on lines 16–17 get the right result, regardless of the numeric types you’re working with.
How the compiler picks a version
This happens at compile time, before your program ever runs. When the compiler sees power(2, 10), it checks the argument types against every power function you’ve written, and picks the one whose parameters match best. This is called overload resolution.
Since the compiler already knows which power to call before the program starts running, there’s no additional runtime cost.
What counts as a different overload
The name plus the parameter types (not the return type) make up a function’s signature. Two functions can share a name as long as their signatures differ.
The compiler distinguishes overloads by:
- how many parameters there are
- what types those parameters are
- what order those types appear in
So all three of these can coexist as overloaded functions:
void log(const std::string& message);void log(const std::string& message, int errorCode);void log(int errorCode, const std::string& message);One thing that doesn’t count as a valid overload is a function that differs only in return type. This fails to compile:
int getValue();double getValue(); // error: return type alone isn't enoughTo see why the return type alone isn’t enough, picture calling getValue(); and throwing away the result. There’s no argument to distinguish which getValue you meant, so the compiler has nothing to go on.
Checkpoint
Which pair of function declarations forms a valid overload?
void display(int score);
void display(double score);
vs
int total(int a, int b, int c);
double total(int a, int b, int c);Which of these functions runs against the function call notify(3, "Sam")?
void notify(std::string user, int count);
void notify(int count, std::string user);You’re writing a describe function for a catalog. One version should handle a product’s numeric ID, another should handle its price. Which pair of signatures are valid overloads?