C++ Function Overloading: Rules, Ambiguity, and Name Mangling
이 글의 핵심
Same name, different parameters: how overload resolution works, why return type alone cannot overload, and how to avoid ambiguous calls.
What is function overloading?
Same name, different parameters—multiple functions share an identifier.
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() {
std::cout << add(1, 2) << std::endl; // 3 (int)
std::cout << add(1.5, 2.5) << std::endl; // 4.0 (double)
std::cout << add(1, 2, 3) << std::endl; // 6 (three args)
}
Overloading rules
// ✅ Different arity
void func(int x);
void func(int x, int y);
// ✅ Different parameter types
void func(int x);
void func(double x);
// ✅ const differences (pointer/reference)
void func(int* ptr);
void func(const int* ptr);
// ❌ Return type only (not allowed)
int func(int x);
// double func(int x); // error
Practical examples
Example 1: Print overloads
#include <iostream>
#include <vector>
void print(int x) {
std::cout << "int: " << x << std::endl;
}
void print(double x) {
std::cout << "double: " << x << std::endl;
}
void print(const std::string& s) {
std::cout << "string: " << s << std::endl;
}
void print(const std::vector<int>& vec) {
std::cout << "vector: ";
for (int x : vec) {
std::cout << x << " ";
}
std::cout << std::endl;
}
int main() {
print(42);
print(3.14);
print(std::string("Hello"));
print(std::vector<int>{1, 2, 3});
}
Example 2: Max functions
int max(int a, int b) {
return a > b ? a : b;
}
double max(double a, double b) {
return a > b ? a : b;
}
int max(int a, int b, int c) {
return max(max(a, b), c);
}
template<typename T>
T max(const std::vector<T>& vec) {
if (vec.empty()) {
throw std::invalid_argument("empty vector");
}
T maxVal = vec[0];
for (const auto& val : vec) {
if (val > maxVal) {
maxVal = val;
}
}
return maxVal;
}
int main() {
std::cout << max(10, 20) << std::endl;
std::cout << max(1.5, 2.5) << std::endl;
std::cout << max(1, 2, 3) << std::endl;
std::vector<int> nums = {5, 2, 8, 1, 9};
std::cout << max(nums) << std::endl;
}
Example 3: Constructor overloading
class String {
private:
char* data;
size_t length;
public:
String() : data(nullptr), length(0) {}
String(const char* str) {
length = strlen(str);
data = new char[length + 1];
strcpy(data, str);
}
String(char c, size_t count) {
length = count;
data = new char[length + 1];
memset(data, c, length);
data[length] = '\0';
}
String(const String& other) {
length = other.length;
data = new char[length + 1];
strcpy(data, other.data);
}
~String() {
delete[] data;
}
};
int main() {
String s1;
String s2("Hello");
String s3('*', 10);
String s4(s2);
}
Example 4: Search overloads
#include <vector>
#include <string>
int find(const std::vector<int>& vec, int target) {
for (size_t i = 0; i < vec.size(); i++) {
if (vec[i] == target) {
return static_cast<int>(i);
}
}
return -1;
}
int find(const std::vector<std::string>& vec, const std::string& target) {
for (size_t i = 0; i < vec.size(); i++) {
if (vec[i] == target) {
return static_cast<int>(i);
}
}
return -1;
}
template<typename T, typename Predicate>
int find(const std::vector<T>& vec, Predicate pred) {
for (size_t i = 0; i < vec.size(); i++) {
if (pred(vec[i])) {
return static_cast<int>(i);
}
}
return -1;
}
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::cout << find(numbers, 3) << std::endl;
std::vector<std::string> words = {"apple", "banana", "cherry"};
std::cout << find(words, std::string("banana")) << std::endl;
std::cout << find(numbers, [](int x) { return x > 3; }) << std::endl;
}
const overloading
class Array {
private:
int data[10];
public:
int& operator[](size_t index) {
return data[index];
}
const int& operator[](size_t index) const {
return data[index];
}
};
int main() {
Array arr;
arr[0] = 10;
const Array& constArr = arr;
int x = constArr[0];
}
Common pitfalls
Pitfall 1: Ambiguous calls
void func(int x) {
std::cout << "int" << std::endl;
}
void func(double x) {
std::cout << "double" << std::endl;
}
int main() {
func(10);
func(3.14);
// func(10.0f); // ambiguous: float -> int or double?
func(static_cast<int>(10.0f));
func(static_cast<double>(10.0f));
}
Pitfall 2: Default arguments vs overloads
// ❌ Ambiguous
void func(int x) {
std::cout << "one arg" << std::endl;
}
void func(int x, int y = 0) {
std::cout << "two args" << std::endl;
}
int main() {
// func(10); // error: ambiguous
func(10, 20);
}
// ✅ Different names
void func1(int x);
void func2(int x, int y = 0);
Pitfall 3: Pointer vs array parameters
void func(int* ptr) {
std::cout << "pointer" << std::endl;
}
void func(int arr[]) {
std::cout << "array" << std::endl;
}
// Error: same signature (array decays to pointer)
Pitfall 4: Return type only
int getValue() {
return 42;
}
// double getValue() { return 3.14; } // error
int getIntValue() { return 42; }
double getDoubleValue() { return 3.14; }
Overload resolution sketch
void func(int x) { std::cout << "int" << std::endl; }
void func(double x) { std::cout << "double" << std::endl; }
void func(const std::string& s) { std::cout << "string" << std::endl; }
int main() {
func(10);
func(3.14);
func("hello");
char c = 'A';
func(c);
short s = 10;
func(s);
}
FAQ
Q1: When to use overloading?
A:
- Same operation, different types
- Different arity
- Convenience overloads
Q2: Overloading vs templates?
A:
- Overloading: type-specific implementations
- Templates: same logic, generic
Q3: Performance impact?
A: None at runtime; resolved at compile time.
Q4: Overload by return type?
A: Not allowed; distinguish by parameters.
Q5: Ambiguous calls?
A: Use explicit casts or different names.
Q6: Learning resources?
A:
- Effective C++
- cppreference.com
- C++ Primer
Related posts (internal links)
- C++ Default Arguments
- C++ Functions: Complete Beginner Guide
- C++ Name Mangling
Practical tips
Debugging
- Compiler warnings first.
- Minimal repro cases.
Performance
- Profile, don’t guess.
Code review
- Team conventions.
Practical checklist
Before coding
- Right fit?
- Maintainable?
- Performance?
While coding
- Warnings?
- Edge cases?
- Errors?
During review
- Clear?
- Tests?
- Docs?
Keywords (search)
C++, overloading, function, resolution, templates
Related posts
- C++ name hiding