Docs
README
Function Overloading in C++
Table of Contents
- •Introduction
- •How Overloading Works
- •Overload Resolution
- •Common Use Cases
- •Ambiguity and Pitfalls
- •Overloading vs Default Arguments
- •Operator Overloading Preview
- •Best Practices
Introduction
Function overloading allows multiple functions with the same name but different parameters. The compiler selects the correct version based on the arguments.
int add(int a, int b); // For integers
double add(double a, double b); // For doubles
string add(string a, string b); // For strings
Why Overload?
- •Consistent interface for similar operations
- •Avoid inventing many function names (addInt, addDouble, addString)
- •Cleaner, more intuitive API
How Overloading Works
Function Signature
The signature determines uniqueness:
- •Function name
- •Number of parameters
- •Type of parameters
- •Order of parameters
NOT part of signature:
- •Return type
- •Parameter names
// Valid overloads - different signatures
void print(int x);
void print(double x);
void print(int x, int y);
void print(string s);
// INVALID - only differs by return type
int getValue();
double getValue(); // ERROR: redefinition
Name Mangling
The compiler internally renames functions to encode parameter types:
print(int) → _Z5printi
print(double) → _Z5printd
print(int,int) → _Z5printii
Overload Resolution
When you call an overloaded function, the compiler:
- •Finds all candidates with that name
- •Filters to viable functions (matching parameter count)
- •Ranks by conversion quality
- •Selects best match or reports ambiguity
Matching Priority (Best to Worst)
| Priority | Match Type | Example |
|---|---|---|
| 1 | Exact match | print(5) → print(int) |
| 2 | Promotion | print('a') → print(int) (char→int) |
| 3 | Standard conversion | print(3.14) → print(int) (double→int) |
| 4 | User-defined conversion | Custom conversion operators |
Examples
void func(int x); // (1)
void func(double x); // (2)
void func(long x); // (3)
func(10); // Exact → (1)
func(3.14); // Exact → (2)
func(10L); // Exact → (3)
func('A'); // Promotion char→int → (1)
func(10.0f); // Promotion float→double → (2)
Common Use Cases
1. Different Types
void print(int value) {
cout << "Integer: " << value << endl;
}
void print(double value) {
cout << "Double: " << value << endl;
}
void print(const string& value) {
cout << "String: " << value << endl;
}
2. Different Number of Arguments
int max(int a, int b) {
return (a > b) ? a : b;
}
int max(int a, int b, int c) {
return max(max(a, b), c);
}
int max(int a, int b, int c, int d) {
return max(max(a, b), max(c, d));
}
3. Optional Parameters
void greet() {
greet("World"); // Call other overload
}
void greet(const string& name) {
greet(name, "Hello");
}
void greet(const string& name, const string& greeting) {
cout << greeting << ", " << name << "!" << endl;
}
4. Container Variants
double average(const vector<int>& nums);
double average(const vector<double>& nums);
double average(const int* arr, size_t size);
Ambiguity and Pitfalls
Ambiguous Calls
void process(int x, double y);
void process(double x, int y);
process(1, 2); // ERROR: ambiguous!
// Both require one conversion
// Fix: explicit cast
process(1, 2.0); // Calls first
process(1.0, 2); // Calls second
const Overloading
class Container {
public:
int& get(int index); // For non-const objects
const int& get(int index) const; // For const objects
};
Container c;
const Container cc;
c.get(0) = 10; // Uses non-const version
int x = cc.get(0); // Uses const version
Reference vs Value Ambiguity
void func(int x); // Value
void func(int& x); // Reference
int n = 5;
func(n); // ERROR: ambiguous!
func(5); // OK: only value works (5 is rvalue)
Default Arguments Interaction
void display(int x, int y = 0);
void display(int x);
display(5); // ERROR: ambiguous!
Overloading vs Default Arguments
| Aspect | Overloading | Default Arguments |
|---|---|---|
| Different logic | ✓ Each has own impl | ✗ Same impl |
| Compile-time binding | At call site | At call site |
| Flexibility | More flexible | Simpler |
| Code duplication | May duplicate | Single function |
When to Use Each
Default Arguments:
// Same logic, just different defaults
void connect(string host, int port = 80, bool ssl = false) {
// Single implementation
}
Overloading:
// Fundamentally different implementations
void sort(vector<int>& v) {
// Integer-specific optimization
}
void sort(vector<string>& v) {
// String comparison logic
}
Operator Overloading Preview
Operators are special functions that can be overloaded:
class Vector2D {
public:
double x, y;
Vector2D operator+(const Vector2D& other) const {
return {x + other.x, y + other.y};
}
Vector2D operator*(double scalar) const {
return {x * scalar, y * scalar};
}
bool operator==(const Vector2D& other) const {
return x == other.x && y == other.y;
}
};
Vector2D a{1, 2}, b{3, 4};
Vector2D c = a + b; // Uses operator+
Vector2D d = a * 2.0; // Uses operator*
bool eq = (a == b); // Uses operator==
(Full coverage in 05_Operator_Overloading)
Best Practices
✅ Do
// Consistent behavior across overloads
int abs(int x);
double abs(double x);
long abs(long x);
// Clear semantic difference
void draw(Point p);
void draw(Line l);
void draw(Circle c);
❌ Don't
// Semantically different operations
void process(int x); // Prints x
void process(string s); // Writes to file
// Confusing - same name, completely different behavior!
// Too similar, easy to call wrong one
void update(int id, string name);
void update(string name, int id);
Guidelines Summary
- •Overload for same conceptual operation on different types
- •Avoid ambiguous parameter combinations
- •Document when behavior differs between overloads
- •Consider templates if logic is identical across types
- •Be careful mixing overloading with default arguments
Quick Reference
// Valid overloads
void f(int);
void f(double);
void f(int, int);
void f(const string&);
// Invalid - return type doesn't distinguish
int f();
double f(); // ERROR
// const overloading (member functions)
T& get();
const T& get() const;
// Ambiguity resolution
void g(int, double);
void g(double, int);
g(1, 2); // ERROR: ambiguous
g(1, 2.0); // OK: first overload
Compile & Run
g++ -std=c++17 -Wall -Wextra examples.cpp -o examples
./examples