Function Overloading
Basic Example
#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;
}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
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
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.
// 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;
}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.