본문 바로가기
  • 여행하고 먹는 즐거운 콘지의하루
프로그래머의 프로그래밍 이야기/C++ Programming

C++ 오버로딩 다양한 사용법 정리

by 콘지 2022. 6. 20.

본 글은 함수 오버로딩에 대해서 살펴보고 사용법 및 주의 사항에 대해서 간략히 설명하겠습니다. 

함수 오버로딩의 개념은 많은 블로그들에서 다루므로 간단하게만 설명하겠습니다. 

 

참고한 문서의 링크를 참고 했으니, 더 자세히 보고 싶으신 분들은 봐주세요(영어ㅠㅠ)

https://docs.microsoft.com/en-us/cpp/cpp/function-overloading?view=msvc-170 

 

Function Overloading

Learn more about: Function Overloading

docs.microsoft.com

 

함수 오버로딩

함수명은 같으나 인자가 다른 함수의 선언을 말합니다.

- C++은 동일한 이름을 가진 1개 이상의 함수를 허용합니다. 이러한 함수들을 "오버로딩되었다" 라고 표현하며 이런 함수들의 차이점은 인자들의 숫자나 타입들이 다른 경우 입니다.

 

대표적인 함수 오버로딩의 예?

printf 라고 할 수 있습니다. 물론 C의 대표적인 함수이긴 하지만 그 예를 생각해보자구요!

printf는 다양한 타입들을 받을수 있습니다. 예를들어서 문자열을 받을 수 있고요, double, int 등 다양한 인자들에 대해서 

그것에 맞게 반응하죠, C++의 오버로딩의 개념으로 생각하면 각 타입들을 받는 printf가 구현되어 있는겁니다.

void printf(double d){ }
void printf(std::string){ }
void printf(int i){ }

다음과 같이, 

여러개의 타입을 받는 printf를 구현하는 것 그것이 함수 오버로딩이라고 할 수 있습니다.

 

그럼 어떨때 오버로딩을 사용할 수 있는데?

우리가 오버로딩을 사용할 수 있는 경우와 사용하지 못하는 경우는 다음 표를 참고해서 작성하면 됩니다.

  • 함수의 리턴 타입이 다른 경우? : 사용 불가
  • 함수의 인자 개수가 다른 경우? : 사용 가능
  • 함수 파라미터 인자의 타입이 다른 경우? : 사용 가능
  • ellipsis(... 가변인자)가 사용되는 경우 : 사용 가능
  • typedef 형태의 사용 : 사용 가능
  • const & volatile의 사용 : 사용 가능

등등이 있는데,  즉, 간략히 하면 리턴타입만 다른 경우는 오버로딩을 사용할 수 없으며

인자의 타입이나, 개수가 다른 경우만 사용할 수 있다 라고 이해 하면 되겠네요:)

 

int print(string s)
{
	printf("case 1"); 
}
int print(double dvalue)
{
	printf("case 2"); 
}
int print(double dvalue, int prec)
{
	printf("case 3");
}

int main(int argc, char *argv[])
{
    const double d = 893094.2987;
    print("aa"); 
	print(d); 
	print(d, 2);	
}

다음은 가장 기초적인 함수 오버로딩을 사용하는 방법입니다!

 

Output

Case 1

Case 2

Case 3

 

내용 설명을 드리면, 

print 란 함수가 오버로딩 되어있고 첫번째 print는 string을 받는 함수

두번째 print는 double 세번째는 double과 int 를 받는 함수가 각각 오버로딩 되어있는 상황에서

main 에서 각각 맞는 오버로딩 된 함수를 호출하는 것을 코드로 표현했네요,

 

이렇게 오버로딩 되어있는 함수들을 정의해놓으면

컴파일러가 오버로딩 된 함수들을 보면서 가장 잘 매칭되는 함수들을 선택하게 됩니다.

여기서 가장 잘 매칭되는 함수들이란 정확하게 매칭되는 함수부터 시작하여 모호하게 매칭되는 함수까지로 찾는 과정을 일컫습니다.

 

컴파일러는 일련의 후보자 오버로딩 함수의 집합을 생성합니다.

후보자 함수들은 정확하게 인자들이 매칭되는 함수부터 인자의 변환이 되어 함수가 호출될 수 있는 것까지 다양하게 선별합니다.

이러한 내용을 논의해보기 위해서 함수#1, 함수#2, 함수#3 으로 마킹되어 있는 오버로딩 함수 3개를 소개할께요

Fraction &Add( Fraction &f, long l );       // 함수1
Fraction &Add( long l, Fraction &f );       // 함수2
Fraction &Add( Fraction &f, Fraction &f );  // 함수3

Fraction F1, F2;

여기서 우리 이렇게 함수를 호출했을때 어떤 오버로딩 함수가 호출될까요 ? 

F1 = Add( F2, 23 );

결과적으로는 함수1이, int를  long으로 바꾸기에 가장 적은 비용이드므로 채택되게 될 것입니다.

파라미터가 long을 받음에도, 암시적인 형변환을 통해 오버로딩 함수가 호출된 것을 볼 수 있습니다. 

F1 = Add( 3, 6 );

이런 경우라면 어떤 함수가 호출될까요? 

#제안1

: 첫번째 파라미터가 int이기 때문에 -> 함수 2 Candidate

#제안2

: 두번째 파라미터가 int이기 때문에 -> 함수 1 Candidate

그래도, 나머지 파라미터의 형변환을 할 수 없기 때문에 오류 메시지가 출력될 것입니다. 

즉, 컴파일러 정도는 인식할 수 있어야 한다.. ㅠㅠ 

 

그 외에도 const/volatile과 같은 함수 오버로딩에 대한 다양한 설명들이 되어 있는데

시간이 되면 다른 속성들도 한번 살펴보도록 할께요!

 

 

 

 

 

반응형

댓글