함수 오버로딩
함수 오버로딩 개요
함수 오버로딩은 같은 이름의 함수를 여러 개 정의할 수 있게 해주는 C++의 강력한 기능입니다.
이는 매개변수의 타입이나 개수가 다른 경우에 가능합니다.
함수 오버로딩을 통해 프로그래머는 직관적인 함수 이름을 유지하면서도 다양한 타입에 대해 작업할 수 있습니다.
함수 오버로딩의 기본 원리
다음은 함수 오버로딩의 간단한 예시입니다.
#include <iostream>
int add(int a, int b) {
std::cout << "Adding integers: " << a << " + " << b << std::endl;
return a + b;
}
double add(double a, double b) {
std::cout << "Adding doubles: " << a << " + " << b << std::endl;
return a + b;
}
int main() {
std::cout << add(5, 3) << std::endl; // int 버전 호출
std::cout << add(3.14, 2.5) << std::endl; // double 버전 호출
return 0;
}
이 예제에서 add
함수는 정수와 실수에 대해 각각 다르게 정의되어 있습니다.
함수 오버로딩의 장점
1. 직관적인 함수 이름 사용 : 같은 동작을 하는 함수들에 대해 일관된 이름을 사용할 수 있습니다.
2. 타입에 따른 적절한 구현 : 각 타입에 최적화된 구현을 제공할 수 있습니다.
3. 코드의 가독성 향상 : 함수의 목적이 명확해지고, 사용하기 쉬워집니다.
4. 타입 안전성 : 컴파일러가 적절한 함수를 선택하므로 타입 관련 오류를 줄일 수 있습니다.
함수 오버로딩 해결 과정
컴파일러는 다음 순서로 함수 호출을 해결합니다.
- 정확한 타입 일치
- 승격 (예 :
char
→int
,float
→double
) - 표준 변환 (예 :
int
→double
,double
→int
) - 사용자 정의 변환
#include <iostream>
void print(int i) {
std::cout << "Integer: " << i << std::endl;
}
void print(double d) {
std::cout << "Double: " << d << std::endl;
}
int main() {
print(5); // print(int) 호출
print(3.14); // print(double) 호출
print('A'); // print(int) 호출 (char가 int로 승격)
return 0;
}
오버로딩 주의사항
- 반환 타입만 다른 경우 오버로딩 불가
int getValue();
double getValue(); // 컴파일 오류!
- 모호한 호출 피하기
void print(int i, double d) { /*...*/ }
void print(double d, int i) { /*...*/ }
print(1, 1); // 모호한 호출, 컴파일 오류!
- 기본 매개변수와의 상호작용
void display(int i) { /*...*/ }
void display(int i, int j = 0) { /*...*/ }
display(10); // 모호한 호출, 컴파일 오류!
함수 템플릿과 오버로딩
함수 템플릿과 일반 함수를 함께 사용할 때, 컴파일러는 가장 특수화된 버전을 선택합니다.
#include <iostream>
#include <string>
template <typename T>
void print(T value) {
std::cout << "Template: " << value << std::endl;
}
void print(int value) {
std::cout << "Specialized for int: " << value << std::endl;
}
int main() {
print(5); // int 특수화 버전 호출
print(3.14); // 템플릿 버전 호출
print("Hello"); // 템플릿 버전 호출
return 0;
}
연산자 오버로딩 소개
함수 오버로딩의 개념은 연산자에도 적용될 수 있습니다.
#include <iostream>
class Complex {
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
void display() const {
std::cout << real << " + " << imag << "i" << std::endl;
}
private:
double real, imag;
};
int main() {
Complex c1(3, 2), c2(1, 7);
Complex result = c1 + c2;
result.display(); // 출력: 4 + 9i
return 0;
}
연습 문제
- 정수, 실수, 문자열을 인자로 받아 각각의 타입에 맞는 출력을 하는
print
함수를 오버로딩하여 구현하세요. - 2차원 및 3차원 좌표를 표현하는
Point2D
와Point3D
클래스를 만들고,+
연산자를 오버로딩하여 좌표의 덧셈을 구현하세요.
참고자료
- C++ 공식 문서의 함수 오버로딩 섹션 : Function overloading
- "Effective C++" by Scott Meyers (항목 26 : 매개변수에 의존하는 함수들은 오버로드하는 것이 좋다)
- "C++ Templates : The Complete Guide" by David Vandevoorde, Nicolai M. Josuttis, and Douglas Gregor
- C++ Core Guidelines의 함수 오버로딩 관련 규칙 : F.15: Prefer simple and conventional ways of passing information