C & C++ 기초 개념 정리(4) - Overloading
Function Overloading
함수 오버로딩은 동일한 이름의 함수를 여러개 정의할 수 있도록 하는 기능입니다. 동일한 작업을 수행하지만 입력 데이터 유형이 다른 경우 사용할 수 있습니다.
C++ 컴파일러는 function signature(함수 이름, parameter type, number of parameters, order of parameters)로서 함수를 인식합니다. 따라서 함수의 이름이 같더라도, 다른 parmeter들을 이용한다면 하나의 이름 아래 다양한 parameter를 사용하는 서로 다른 함수를 정의할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
// 두 수의 합을 계산하는 함수
int sum(int a, int b) {
return a + b;
}
// 세 수의 합을 계산하는 함수
int sum(int a, int b, int c) {
return a + b + c;
}
int main() {
cout << "정수 합: " << add(3, 4) << endl; // 첫번쨰 함수 호출
cout << "실수 합: " << add(3, 4, 5) << endl; // 두번째 함수 호출
return 0;
}
함수 시그니처에는 반환형이 포함되지 않기 때문에, 반환형만 다른 오버로딩은 허용되지 않습니다.
1
2
int sum(int a, int b);
double sum(int a, int b); // compile error
Priority order of overloaded function match
C++에서는 오버로딩된 함수가 호출될 때, 가장 적합한 함수를 선택하기 위해 다음과 같은 우선순위를 따릅니다:
- Exact Match
전달된 argument의 타입/개수와 함수의 parameter 타입/개수가 정확히 일치하는 경우.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <iostream> using namespace std; int sum(int a, int b) { return a + b; } double sum(int a, double b) { return a + b; } int main() { sum(1, 2); // 첫번째 함수 호출 return 0; }
Promotion Match
Exact match를 찾을 수 없을 때, 해당 단계로 넘어옵니다. 전달된 argument가 함수 parameter 타입으로 승격(promotion)될 수 있는 경우, 승격의 횟수가 가장 적은 함수가 선택됩니다. 이때 승격은 데이터 타입의 크기와 표현 범위가 더 큰 타입으로 변환되는 것(int
→double
,float
→double
)을 의미합니다.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <iostream> using namespace std; int sum(int a, int b, double c) { return a + b + c; } double sum(int a, double b, double c) { return a + b + c; } int main() { sum(1, 2, 3); // 첫번째 함수의 promotion 횟수는 2회 -> 첫번째 함수 호출 return 0; }
Standard Conversion Match
Promotion으로도 match된 함수를 찾을 수 없다면 해당 단계로 넘어오게 됩니다.
Standard Conversion Match는 전달된 argument가 함수 parameter 타입으로 표준 변환(standard conversion)을 통해 일치할 수 있는 경우를 의미합니다. 표준 변환은 데이터 타입 간의 암시적 변환을 포함하며, 예를 들어bool
→int
,char
→int
등이 이에 해당합니다.
promotion의 반대인 demotion 역시 이 단계에 포함됩니다.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#include <iostream> using namespace std; void f(double a, int b) { cout << "f(double, int)" << endl; } void f(double a, long b) { cout << "f(double, long)" << endl; } int main() { short s = 1; bool b = true; f(s, b); // f(double, int) }
위 예제에선
short
→double
의 promotion이 두 함수 모두 첫번째 argument에서 필요합니다. 하지만bool
→int
의 범위가bool
→long
의 범위보다 좁기 때문에 첫번째 함수가 선택됩니다.Ambiguity 함수 오버로딩에서 호출할 수 있는 함수가 여러 개 존재하지만, 위의 우선순위 규칙을 통해 단일 함수를 선택할 수 없는 경우, 컴파일러는 ambiguity 오류를 발생시킵니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <iostream> using namespace std; void f(int a, double b) { cout << "f(int, double)" << endl; } void f(double a, int b) { cout << "f(double, int)" << endl; } int main() { f(1, 2); // 컴파일 오류: ambiguity 발생 return 0; }
위 예제에서
f(1, 2)
호출은 두 함수 모두와 일치할 수 있지만, 두 함수 모두에 대해 각기 다른 argument에서 promotion이 1회 필요하기 때문에, 어느 하나가 더 적합하다고 판단할 수 없기 때문에 컴파일러는 오류를 발생시킵니다.
따라서 함수 오버로딩을 사용할 때는 이러한 모호성을 피하도록 주의해야 합니다.
Default Argument
Default argument가 존재할 때에는, 함수에 전달된 argument만 봤을 때 default argument를 제외하고 정확히 일치하는 시그니처가 존재하면, 그건 Exact Match로 간주됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
void f(int a, int b = 100) {
cout << "f(int, int=100)" << endl;
}
void f(double a) {
cout << "f(double)" << endl;
}
int main() {
f(1); // f(int, int=100)
}
따라서 다음과 같이 작성하면, ambiguous 에러가 발생합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
void f(int a, int b = 100) {
cout << "f(int, int=100)" << endl;
}
void f(double a) {
cout << "f(double)" << endl;
}
void f(int a) {
cout << "f(int)" << endl;
}
int main() {
f(1); // error: call of overloaded 'f(int)' is ambiguous
}
해당 포스트는 서울대학교 전기정보공학부 정교민 교수님의 프로그래밍방법론 25-1학기 강의를 정리한 내용입니다.