함수 오버로딩(Function Overloading)은 메서드 오버로딩이라고도 부르며, 객체 지향 프로그래밍에서 널리 활용되는 다형성(Polymorphism) 개념이 제공하는 대표적인 기능입니다. 같은 이름의 함수를 매개변수 구성만 바꿔 여러 번 정의할 수 있어 코드의 가독성과 재사용성을 크게 높여 줍니다.
함수 오버로딩이 성립하려면 다음 조건을 충족해야 합니다.
- 함수 이름이 서로 같아야 합니다.
- 컴파일러가 호출 시점에 함수를 구분할 수 있도록 매개변수의 개수, 타입 또는 순서 중 하나 이상이 달라야 합니다.
- 반환 타입은 오버로딩 판단 기준에 포함되지 않습니다. 따라서 반환 타입만 다른 함수는 오버로딩할 수 없습니다.
오버로딩 성립 여부 예시
int display(int a); int display(float a); // 매개변수 타입이 다르므로 오버로딩 가능 int display(int a); float display(int a); // 반환 타입만 다르므로 오버로딩 불가 (컴파일 오류)
C++에서 오버로딩할 수 없는 경우
1. 함수 이름과 매개변수 개수가 모두 다른 경우
이름과 매개변수 개수가 모두 다른 함수는 애초에 오버로딩 관계가 아니라 서로 완전히 별개의 함수입니다. 아래 예제의 max_two와 max_three는 이름 자체가 다르기 때문에 오버로딩으로 처리되지 않습니다.
#include <iostream>
using namespace std;
int max_two(int a, int b) { // 매개변수 2개
if (a > b)
return a;
else
return b;
}
int max_three(int a, int b, int c) { // 매개변수 3개
if (a > b && a > c)
return a;
else if (b > c)
return b;
else
return c;
}
int main() {
cout << max_two(10, 20) << endl;
cout << max_three(10, 20, 30) << endl;
return 0;
}
2. 함수 이름은 같지만 반환 타입만 다른 경우
매개변수 목록이 동일한데 반환 타입만 다른 두 함수는 오버로딩할 수 없습니다. 컴파일러는 함수 호출 시점에 어떤 버전을 선택해야 할지 판단할 수 없어 'return type만 다른 함수는 오버로딩 불가'라는 오류를 발생시킵니다.
#include <iostream>
using namespace std;
int max_two(int a, int b) {
return (a > b) ? a : b;
}
float max_two(int a, int b) { // 오류: 반환 타입만 다름
return (a > b) ? a : b;
}
int main() {
cout << max_two(10, 20);
return 0;
}
3. 정적(static) 멤버 함수와 일반 멤버 함수가 충돌하는 경우
오버로딩 조건을 모두 갖춘 것처럼 보여도, 클래스 안에서 정적 멤버 함수와 동일한 이름·동일한 매개변수 목록을 가진 비정적(non-static) 멤버 함수를 함께 선언하면 컴파일 오류가 발생합니다. 두 함수는 this 포인터 유무만 다를 뿐 외부에서 보는 시그니처가 사실상 같아 컴파일러가 구분하지 못하기 때문입니다.
#include <iostream>
class Check {
public:
static void test(int i) { } // 정적 멤버 함수
void test(int i) { } // 오류: 동일한 매개변수 목록으로 선언 불가
};
int main() {
Check ch;
return 0;
}
4. 기본 인수(default argument)만 다른 경우
두 함수의 이름과 매개변수 목록이 완전히 같고 한쪽에만 기본 인수가 지정된 경우에도 오버로딩은 성립하지 않습니다. 컴파일러는 이를 같은 함수의 재선언(redeclaration)으로 간주해 오류를 발생시키며, func_1(10, 20)처럼 인수를 모두 전달하는 호출 역시 어느 함수를 의미하는지 모호해집니다.
#include <iostream>
using namespace std;
int func_1(int a, int b) {
return a * b;
}
int func_1(int a, int b = 40) { // 오류: 기본 인수만 다름 → 재선언 오류
return a + b;
}
int main() {
cout << func_1(10, 20);
return 0;
}
마무리
정리하면, C++의 함수 오버로딩은 함수 이름이 같고 매개변수 목록이 구분 가능할 때에만 성립합니다. 반환 타입의 차이, 기본 인수의 유무, 정적/비정적 멤버 함수 간의 충돌은 오버로딩으로 인정되지 않으므로 함수를 설계할 때 반드시 유의해야 합니다.