Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++에서 함수 오버로딩이 불가능한 경우 총정리

C++는 함수 오버로딩(Function Overloading)을 지원하는 언어입니다. 즉, 같은 이름의 함수라도 매개변수의 개수나 타입이 다르면 여러 버전을 정의할 수 있습니다. 하지만 모든 경우에 오버로딩이 허용되는 것은 아닙니다. 컴파일러가 함수들을 구분할 수 없는 상황에서는 오버로딩이 성립하지 않으며, 이 경우 컴파일 에러가 발생합니다.

이 글에서는 C++에서 함수 오버로딩이 불가능한 대표적인 다섯 가지 경우를 코드 예제와 함께 살펴보겠습니다.

1. 반환 타입만 다른 경우

함수의 시그니처(함수 이름과 매개변수 목록)가 완전히 동일하고 반환 타입만 다를 때는 오버로딩할 수 없습니다. C++ 컴파일러는 함수를 구별할 때 반환 타입을 고려하지 않기 때문입니다.

int my_func() {
    return 5;
}
char my_func() {   // 컴파일 에러: 반환 타입만 다름
    return 'd';
}

호출 시점에 어떤 함수를 호출해야 하는지 판단할 근거가 없으므로, 두 함수는 동일한 함수로 간주되어 재정의 오류가 발생합니다.

2. 클래스 멤버 함수의 이름과 매개변수 목록이 같은 경우

클래스 내부에서 멤버 함수들의 이름과 매개변수 목록이 완전히 동일하다면, static 여부와 관계없이 오버로딩할 수 없습니다.

class My_Class {
    static void func(int x) {
        // Something
    }
    void func(int x) {   // 컴파일 에러: 동일한 시그니처
        // something
    }
};

static 멤버 함수와 일반 멤버 함수의 차이는 함수 시그니처의 일부로 취급되지 않으므로, 컴파일러 입장에서는 같은 함수가 두 번 선언된 것과 마찬가지입니다.

3. 포인터(*)와 배열([])만 다른 경우

매개변수 선언에서 포인터(*)와 배열([]) 표기만 다른 경우에는 두 매개변수가 동일한 타입으로 간주됩니다. 배열은 함수 인자로 전달될 때 자동으로 포인터로 decay(붕괴)되기 때문입니다.

int my_func(int *arr) {
    // Do something
}
int my_func(int arr[]) {   // 컴파일 에러: int*와 동일하게 해석됨
    // do something
}

즉, int arr[]는 함수 매개변수 위치에서 int *arr와 정확히 같은 의미를 가지므로 오버로딩이 성립하지 않습니다.

4. const / volatile 한정자만 다른 경우

값 타입(value type) 매개변수에서 const 또는 volatile 한정자의 유무만 다른 경우에도 두 함수는 동일한 시그니처로 취급됩니다.

int my_func(int x) {
    // Do something
}
int my_func(const int x) {   // 컴파일 에러: 값 전달 시 const는 무시됨
    // do something
}

함수 내부에서 매개변수가 수정되지 않는다는 것은 호출자 입장에서 아무런 영향을 주지 않기 때문에, 최상위(top-level) const는 오버로드 구분 기준이 되지 않습니다. 참고로 포인터나 참조 타입의 경우(const int* vs int*)에는 한정자가 시그니처의 일부가 되어 오버로딩이 가능합니다.

5. 기본 인자(default argument)만 다른 경우

매개변수 목록이 같고 기본 인자의 유무나 값만 다른 경우에도 오버로딩할 수 없습니다. 기본 인자는 함수 시그니처에 포함되지 않기 때문입니다.

int my_func(int a, int b) {
    // Do something
}
int my_func(int a, int b = 50) {   // 컴파일 에러: 기본 인자는 시그니처에 불포함
    // do something
}

두 함수 모두 my_func(10) 또는 my_func(10, 20) 형태로 호출될 수 있어 모호성(ambiguity)이 발생하며, 컴파일러는 이를 허용하지 않습니다.

마무리

정리하면, C++에서 함수 오버로딩이 가능하려면 컴파일러가 매개변수의 개수, 타입, 순서를 기준으로 함수들을 명확히 구분할 수 있어야 합니다. 반환 타입, static 여부, 포인터와 배열 표기의 차이, 값 타입의 const/volatile 한정자, 기본 인자의 차이는 모두 시그니처 구분에 사용되지 않으므로 오버로딩이 불가능합니다. 오버로딩 설계 시 이러한 제약 조건을 반드시 염두에 두어야 컴파일 에러와 모호성 문제를 예방할 수 있습니다.