본문으로 바로가기

  

 

함수 오버로딩의 이해(Function Overloading)

int MyFunc(int num)
{
      num++;
      return num;
}

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

void main()
{
    MyFunc(20);  // MyFunc(int num) 함수의 호출
    MyFunc(30, 40);  // MyFunc(int a, int b) 함수의 호출
    return 0;
}

위의 main 함수에 삽입된 주석에서 설명하듯이 
함수호출 시 전달되는 인자를 통해서 호출하고자 하는 함수의 구분이 가능하기 때문에
매개변수의 선언형태가 다르다면, 동일한 이름의 함수 정의를 허용할 수 있다.
C++은 이를 사용하고 있으며, 이러한 형태의 함수 정의를 가리켜 "함수 오버로딩"이라 한다.

 


함수의 오버로딩이 가능하려면 매개변수의 선언이 달라야 한다.

#include <iostream>

void Function()
{
	std::cout << "MyFunc(void) called" << std::endl;
}

void Function(char C)
{
	std::cout << "MyFunc(char C) called" << std::endl;
}

void Function(int a, int b)
{
	std::cout << "MyFunc(int a, int b)" << std::endl;
}

void main()
{
	Function();
	Function('A');
	Function(12, 13);
	
	system("pause");
}

 

 

매개변수의 디폴트 값(Default Value)
여기서 말하는 '디폴트 값'이란 기본적으로 설정되어 있는 값을 의미한다.

함수의 매개변수를 다음의 형태로 선언하는 것이 가능하다.

int MyFuncOne(int num=7)
{
    return num+1;
}

int MyFuncTwo(int num1=5, int num2=7)
{
    return num1+num2;
}

 

여기서 MyFuncOne의 매개변수 선언은 int num=7
그리고 이는 다음의 의미를 지닌다.
"함수호출 시 인자를 전달하지 않으면 7이 전달된 것으로 간주하겠다."
따라서 다음 두 함수 호출문은 완전히 동일하다.
MyFuncOne(); // 7이 전달된 것으로 간주
MyFuncOne(7);

 


이어서 MyFuncTwo의 매개변수 선언은 int num1=5, int num2=7
그리고 이는 다음의 의미를 지닌다.
"함수호출 시 인자를 전달하지 않으면 num1에 5가, num2에 7이 전달된 것으로 간주하겠다."
따라서 다음 두 함수 호출문은 완전히 동일하다.
MyFuncTwo(); // 5와 7이 전달된 것으로 간주
MyFuncTwo(5, 7);

 


예제)

#include <iostream>

int Adder(int num1 = 1, int num2 = 2)
{
	return num1 + num2;
}

void main()
{
	std::cout << Adder() << std::endl;
	std::cout << Adder(5) << std::endl; 
//위의 행에서는 Adder함수를 호출하면서 인자를 하나만 전달하고 있다.
//이러한 경우 인자는 첫 번째 매개변수로 전달된다. 따라서 두 번째 매개변수 num2에는 2가 전달된 것으로 간주된다.
	std::cout << Adder(3, 5) << std::endl;

	system("pause");
}

매개변수에 디폴트 값이 설정되어 있으면, 선언된 매개변수의 수보다 적은 수의 인자전달이 가능하다.
그리고 전달되는 인자는 왼쪽에서부터 채워져 나가고, 부족분은 디폴트 값으로 채워진다.
디폴트 값은 함수의 선언 부분에만 표현하면 된다.

 


부분적 디폴트 값 설정
다음과 같이 오른쪽 매개변수의 디폴트 값을 비우는 형태로는 디폴트 값을 지정할 수 없다.

int YourFunc(int num1=3, int num2=5, int num3){ ...}

 

반드시 오른쪽 매개변수의 디폴트 값부터 채우는 형태로 정의해야 한다.

int YourFunc(int num1, int num2, int num3=30){ ...} [O]
int YourFunc(int num1, int num2=20, int num3=30){ ...} [O]
int YourFunc(int num1=10, int num2=20, int num3=30){ ...} [O]

int WrongFunc(int num1=10, int num2, int num3) { ...} [X]
int WrongFunc(int num1=10, int num2=20, int num3) { ...} [X]

 

 

반드시 오른쪽부터 채울 것을 요구하는 이유는 ?
"함수에 전달되는 인자가 왼쪽에서부터 오른쪽으로 채워지기 때문이다."

//DefaultValue3.cpp
#include <iostream>

int BoxVolume(int length, int width = 1, int height = 1);

void main()
{
	std::cout << "[3, 3, 3,] : " << BoxVolume(3, 3, 3) << std::endl;
	std::cout << "[5,5,D] : " << BoxVolume(5, 5) << std::endl;
	std::cout << "[7,D,D] : " << BoxVolume(7) << std::endl;
	// std::cout << "[D,D,D] : " << BoxVolume() << std::endl; 컴파일 에러
	system("pause");
}

int BoxVolume(int length, int width, int height)
{
	return length * width*height;
}

 


문제1)
다음 main 함수에서 필요로 하는 swap 함수를 오버로딩 해서 구현해보자.

#include <iostream>

void main()
{
	int num1 = 20, num2 = 30;
	swap(&num1, &num2);
	std::cout << num1 << ' ' << num2 << std::endl;

	char ch1 = 'A', ch2 = 'Z';
	swap(&ch1, &ch2);
	std::cout << ch1 << ' ' << ch2 << std::endl;

	double dbl1 = 1.111, dbl2 = 5.555;
	swap(&dbl1, &dbl2);
	std::cout << dbl1 << ' ' << dbl2 << std::endl;
}

답 :

#include <iostream>

void swap(int num1, int num2) {
	int tmp;
	tmp = num1;
	num1 = num2;
	num2 = tmp;
	std::cout << num1 << ' ' << num2 << std::endl;
}

void swap(char ch1, char ch2) {
	char tmp;
	tmp = ch1;
	ch1 = ch2;
	ch2 = tmp;
	std::cout << ch1 << ' ' << ch2 << std::endl;
}

void swap(double dbl1, double dbl2) {
	double tmp;
	tmp = dbl1;
	dbl1 = dbl2;
	dbl2 = tmp;
	std::cout << dbl1 << ' ' << dbl2 << std::endl;
}

void main()
{
	swap(20, 30);
	swap('A', 'Z');
	swap(1.111, 5.555);

	system("pause");
}

 

 

문제2)
위 본문의 예제 DefaultValue3.cpp에 정의된 함수 Boxvolume를 '매개변수의 디폴트 값 지정'형태가 아닌, '함수 오버로딩'의 형태로 재 구현해보자. 물론 main함수는 변경하지 않아야 하며, 실행결과도 동일해야 한다.

#include <iostream>

int BoxVolume(int length, int width, int height) {
	return length * width * height;
}

int BoxVolume(int length, int width) {
	return length * width * 1;
}

int BoxVolume(int length) {
	return length * 1 * 1;
}

void main()
{
	std::cout << "[3, 3, 3,] : " << BoxVolume(3, 3, 3) << std::endl;
	std::cout << "[5,5,D] : " << BoxVolume(5, 5) << std::endl;
	std::cout << "[7,D,D] : " << BoxVolume(7) << std::endl;
	// std::cout << "[D,D,D] : " << BoxVolume() << std::endl; 컴파일 에러
	system("pause");
}

 

 

문제3)
다음과 같은 형태로의 함수 오버로딩은 문제가 있다. 어떠한 문제가 있는지 설명해보자.

#include <iostream>

int SimpleFunc(int a = 10)
{
	return a + 1;
}

int SimpleFunc(void)
{
	return 10;
}

 

답 : 매개변수를 입력하면 문제가 되진 않지만, 입력을 하지 않을 경우 컴파일 에러 발생.