[2026] C++ Function Overloading: Rules, Ambiguity, and Name Mangling
이 글의 핵심
Learn C++ function overloading: same name, different parameters. Resolution rules, common ambiguities, default arguments, and how it ties to name mangling.
What is function overloading?
Same name, different parameters—multiple functions share an identifier. 다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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
다음은 cpp를 활용한 상세한 구현 코드입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ✅ 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
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#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
다음은 cpp를 활용한 상세한 구현 코드입니다. 에러 처리를 통해 안정성을 확보합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#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
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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
다음은 cpp를 활용한 상세한 구현 코드입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ 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
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
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
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
int getValue() {
return 42;
}
// double getValue() { return 3.14; } // error
int getIntValue() { return 42; }
double getDoubleValue() { return 3.14; }
Overload resolution sketch
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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)
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?