본문 바로가기
C++

[C++] 함수 오버로딩과 매개변수의 디폴트 값

by 프링글's 2022. 7. 13.

Ⅰ. 함수 오버로딩

C언어에서는 다음과 같이 두개의 함수의 이름이 다른 것을 허용하지 않았다.

예를 들어

int func(int a);
int func(int a, int b);

이런 형식으로 이름이 같은 함수 두개를 구분하지 못해 함수의 이름을 항상 다르게 해야했다.

하지만 우리가 보기엔 이 두 함수를 매개변수를 보고 충분히 구분할 수 있을 것 같아 보인다. 따라서 C++에서는 이렇게 같은 이름의 함수라도 매개변수를 통해 구분할 수 있다면 함수를 정의할 수 있다.

 

이렇게 C언어와 C++에서의 규칙이 다른 이유는 함수를 찾는 방법이 서로 다르기 때문이다.

C언어의 경우 함수를 찾을 때 함수의 이름만을 이용해 찾게 된다. 즉, 위 코드에서는 func이라는 이름만 보고 구분이 불가능하다고 판단한 것이다.

C++의 경우는 함수를 찾을 때 함수의 이름과 매개변수의 선언 두가지를 보게된다. 즉, 위 코드에서 func이라는 이름은 같지만 매개변수가 하나는 int형 1개, 하나는 int형 2개로 달랐기 때문에 구분이 가능 했던 것이다.

 

이렇게 매개변수가 다르고 이름이 같은 함수를 정의하는 것 함수 오버로딩이라고 한다. 

 

매개변수의 차이는 개수 뿐만 아니라 매개변수의 형(type)으로도 구분할 수 있다.

#include <iostream>
void func(int a) {
	std::cout << "func 1" << std::endl;
}
void func(int a, int b) {
	std::cout << "func 2" << std::endl;
}
void func(char a) {
	std::cout << "func 3" << std::endl;
}

int main() {
	func(10);
	func(10, 20);
	func('a');	//매개변수의 개수는 같지만 형(type)이 다름
	return 0;
}

 

func 1
func 2
func 3

 

한가지 주의할 점은 두 함수의 리턴값이 다르면 함수 오버로딩이 불가능하다는 점이다. 즉, 다음과 같은 함수 선언은 불가능하다.

void func(int a);
int func(int a);

반환형은 함수 호출 과정에서 알 수 없는 정보이기 때문에 컴파일 오류로 이어진다.

 

 


Ⅱ. 매개변수의 디폴트 값

C++에서는 함수의 매개변수에 디폴트 값을 설정할 수 있다.

디폴트 값이란 기본적으로 설정되어 있는 값으로 함수의 인자가 전달되지 않으면 디폴트 값으로 간주하게 된다.

int func(int a = 3) {
	return a;
}

위 함수를 호출할 때 func함수에 인자가 전달되지 않을 경우, 즉 func()과 같이 사용한 경우, a의 값에 3이 전달된 것으로 간주하고 3을 리턴한다.

 

만약 다음과 같이 매개변수는 두개인데 전달된 인자가 하나인 경우도 마찬가지로 디폴트 값이 전달된 것으로 간주한다.

#include <iostream>
int func(int a = 3, int b = 7) {
	return a + b;
}
int main(){
    std::cout << func(5) << std::endl;
    return 0;
}

대신 이 경우 전달되는 인자는 왼쪽부터 채워지고 나머지는 디폴트로 채워지는 식이다. 따라서 매개변수 a에는 5가 전달되고, 매개변수 b에는 디폴트 값인 7이 전달되게 된다.

 

함수를 별도로 선언하고 아래에서 정의하는 경우, 디폴트 값은 함수를 선언할 때만 표현해주고, 정의할 때는 다시 표현하지 않는다.

#include <iostream>
int func(int a = 3, int b = 7);		//선언시에만 디폴트 값 입력

int main(){
    std::cout << func() << std::endl;
    return 0;
}

int func(int a, int b) {
	return a + b;
}

그 이유는 컴파일 할 때 선언부분에서 디폴트 값이 입력되어있지 않으면 func()과 같이 인자를 전달하지 않은 함수를 컴파일 할 수 없기 때문이다.

 

또한, 부분적으로 디폴트 값을 설정할 수도 있는데, 이때의 주의할 점은 반드시 오른쪽 매개변수부터 디폴트를 채우는 형태여야 한다는 점이다.

int func(int a = 5, int b = 7, int c = 3);		//가능
int func(int a, int b = 7, int c = 3);		//가능
int func(int a , int b, int c = 3);		//가능
int func(int a = 5, int b, int c = 3);		//불가능
int func(int a = 5, int b, int c);		//불가능

아래 두개가 불가능 한 이유는 디폴트 값이 의미있으려면 인자를 전달하지 않을 방법이 있어야 하는데, 인자는 왼쪽부터 채워진다. 따라서 디폴트 값이 없는 b나 c에 인자를 전달하면서 a에 인자를 전달할 방법이 존재하지 않기 때문에 이런 식의 디폴트 값 설정은 불가능하다.

 

한가지 더 주의할 점은 디폴트 값을 설정한 상태에서 함수 오버로딩에 제한되는 부분이 있다는 점이다. 다시 말해, 만약 디폴트 값이 정해져있다면 함수에 전달할 수 있는 인자의 수도 여러개일 것이다. 따라서 선언시의 매개변수가 분명히 달라도 함수 호출시 구분하지 못하는 경우가 생겨 함수 오버로딩이 불가능할 수 있다.

물론 디폴트 값을 감안하고도 매개변수로 구분할 수 있는 함수라면 함수 오버로딩이 가능하다.

int func(int a, int b = 2);
int func(int a);			//불가능
int func();				//가능

 

'C++' 카테고리의 다른 글

[C++] 이름공간(네임스페이스)  (0) 2022.09.25
[C++] C++의 입출력 방식 std::cout, std::cin  (0) 2022.07.13

댓글