CppFunction Overloading

Function Overloading

Function overloading lets you define multiple functions with the same name as long as they have different parameter lists (different number, order, or types of parameters). The compiler picks the right one to call based on the arguments you provide.
Basic Example

CPP
#include <iostream>
using namespace std;

int add(int a, int b) {
    return a + b;
}

double add(double a, double b) {
    return a + b;
}

int add(int a, int b, int c) {
    return a + b + c;
}

int main() {
    cout << add(2, 3) << endl;         // calls add(int, int)      -> 5
    cout << add(2.5, 3.5) << endl;     // calls add(double, double) -> 6
    cout << add(1, 2, 3) << endl;      // calls add(int, int, int)  -> 6
    return 0;
}
All three functions are named add, but they take different parameter types or counts, so the compiler can tell them apart. Note that the return type alone is not enough to distinguish overloads — the parameter list must differ.
How Overload Resolution Works
When you call an overloaded function, the compiler looks at the number and types of the arguments you passed and tries to find the best matching overload. Roughly, in order of preference, it looks for: an exact type match, a match requiring only minor promotions (like int to double), and finally a match requiring a user-defined conversion. If no single overload is clearly the best match, the call fails to compile.

CPP
void show(int x)    { cout << "int: " << x << endl; }
void show(double x) { cout << "double: " << x << endl; }

int main() {
    show(5);     // exact match -> show(int)
    show(5.0);   // exact match -> show(double)
    show(5.5f);  // float promotes to double -> show(double)
    return 0;
}
Ambiguous Overloads
Warning
If the compiler cannot determine a single best match — for example, two overloads are equally good candidates for the given argument — it reports an ambiguous call error and refuses to compile. This commonly happens with implicit conversions that could go multiple ways.

CPP
void print(int x)    { cout << "int" << endl; }
void print(float x)  { cout << "float" << endl; }

int main() {
    print(5);     // fine - exact match to print(int)
    // print(5.0);  // ERROR: ambiguous - double could convert to
                     // either int or float, and neither is a better match
    return 0;
}
Overloading vs Default Arguments

Both function overloading and default arguments (covered next) let a function accept a variable number of effective inputs, but they solve it differently. Overloading defines genuinely separate functions; default arguments (next page) let a single function make trailing parameters optional by giving them a fallback value.

CPP
// Overloading approach: two full function definitions
void log(string msg) {
    cout << "[INFO] " << msg << endl;
}
void log(string msg, string level) {
    cout << "[" << level << "] " << msg << endl;
}

// Default-argument approach: one function, one optional parameter
void logDefault(string msg, string level = "INFO") {
    cout << "[" << level << "] " << msg << endl;
}
Tip
Prefer default arguments when the "variants" only differ by omitting trailing parameters with sensible fallbacks. Prefer overloading when the variants genuinely need different logic or different parameter types, not just different defaults.
Key Points
  • Overloaded functions share a name but differ in the number, order, or types of their parameters.

  • Return type alone cannot distinguish overloads.

  • The compiler chooses the best-matching overload using exact matches, then promotions, then conversions.

  • An ambiguous call - where no overload is a clearly better match - is a compile-time error.

  • Use overloading for genuinely different behavior; use default arguments for simple optional trailing parameters.