기본 매개변수
함수 오버로딩은 유용하지만, 매개변수의 개수나 타입이 조금씩 다른 여러 함수를 반복해서 정의해야 하는 경우도 있습니다.
예를 들어 거의 동일한 작업을 수행하지만, 몇몇 선택적인 매개변수만 다르게 전달하고 싶을 때 말이죠.
이러한 상황에서 코드의 중복을 줄이고 함수 호출을 더욱 유연하게 만드는 C++의 기능이 바로 기본 매개변수(Default Arguments) 입니다.
이 장에서는 기본 매개변수가 무엇인지, 어떻게 사용하는지, 그리고 사용 시 주의할 점에 대해 알아보겠습니다.
기본 매개변수란 무엇인가?
기본 매개변수는 함수를 선언하거나 정의할 때, 특정 매개변수에 기본값(default value) 을 지정하는 기능입니다.
이렇게 기본값이 지정된 매개변수는 함수를 호출할 때 해당 인자를 생략할 수 있습니다.
만약 인자가 생략되면 컴파일러는 매개변수에 지정된 기본값을 자동으로 사용합니다.
반환타입 함수이름(타입1 매개변수1, 타입2 매개변수2 = 기본값2, 타입3 매개변수3 = 기본값3);
- 기본값은 상수, 전역 변수, 또는 다른 함수의 호출 결과 등이 될 수 있습니다.
- 중요: 기본 매개변수는 항상 오른쪽에서부터 왼쪽으로 순서대로 지정되어야 합니다. 즉, 기본값이 없는 매개변수 뒤에는 기본값이 있는 매개변수가 올 수 없습니다.
// int func(int a = 10, int b); // 오류: 기본값 없는 매개변수 b가 기본값 있는 매개변수 a 뒤에 있음
// int func(int a, int b = 20, int c); // 오류: 기본값 없는 매개변수 c가 기본값 있는 매개변수 b 뒤에 있음
int func(int a, int b = 20, int c = 30); // OK
int func(int a, int b, int c = 30); // OK
int func(int a = 10, int b = 20, int c = 30); // OK
기본 매개변수의 필요성
- 함수 오버로딩의 대안: 매개변수 몇 개만 다른 유사한 함수들을 여러 개 오버로딩하는 대신, 기본 매개변수를 사용하여 하나의 함수로 대체할 수 있습니다. 이는 코드 중복을 줄이고 유지보수를 용이하게 합니다.
- 유연한 함수 호출: 함수를 호출할 때 모든 인자를 항상 제공하지 않아도 되므로, 함수 사용이 더 편리해집니다.
- 선택적 인자 구현: 특정 매개변수가 대부분의 경우 동일한 값을 가지거나, 필수가 아닌 선택적 정보를 나타낼 때 유용합니다.
기본 매개변수 사용 예시
메시지와 함께 특정 횟수만큼 반복하는 함수를 만들어봅시다.
횟수를 지정하지 않으면 기본값(예: 1회)으로 출력하게 합니다.
#include <iostream>
#include <string>
// printMessage 함수: 메시지와 반복 횟수를 받지만, count에 기본값 1을 지정
void printMessage(const std::string& message, int count = 1) {
for (int i = 0; i < count; ++i) {
std::cout << message << std::endl;
}
}
int main() {
printMessage("Hello, C++!"); // count 생략 -> 기본값 1 사용
std::cout << "------------------" << std::endl;
printMessage("Welcome!", 3); // count를 3으로 지정
/* 출력:
Hello, C++!
------------------
Welcome!
Welcome!
Welcome!
*/
return 0;
}
printMessage("Hello, C++!")
호출 시 count
인자를 생략했으므로, count
는 기본값인 1
이 됩니다.
printMessage("Welcome!", 3)
호출 시에는 count
에 3
이 명시적으로 전달되므로, 기본값은 무시되고 3
이 사용됩니다.
그래픽 프로그램에서 창의 위치와 크기를 설정하는 함수를 만들어봅시다.
x
, y
좌표와 width
, height
를 받는데, width
와 height
에 기본값을 줄 수 있습니다.
#include <iostream>
// x, y 좌표와 폭, 높이를 받는 함수
// 폭과 높이에 기본값을 설정
void setWindowSize(int x, int y, int width = 800, int height = 600) {
std::cout << "창 설정: X=" << x << ", Y=" << y
<< ", 폭=" << width << ", 높이=" << height << std::endl;
}
int main() {
setWindowSize(10, 20); // X=10, Y=20, 폭=800, 높이=600 (기본값 사용)
setWindowSize(50, 50, 1024); // X=50, Y=50, 폭=1024, 높이=600 (height 기본값 사용)
setWindowSize(0, 0, 1920, 1080); // X=0, Y=0, 폭=1920, 높이=1080 (모든 인자 명시)
/* 출력:
창 설정: X=10, Y=20, 폭=800, 높이=600
창 설정: X=50, Y=50, 폭=1024, 높이=600
창 설정: X=0, Y=0, 폭=1920, 높이=1080
*/
return 0;
}
기본 매개변수와 함수 원형/정의
기본 매개변수는 함수 원형(declaration) 에만 지정하거나, 함수 정의(definition) 에만 지정할 수 있습니다.
두 곳 모두에 지정하면 컴파일 오류가 발생합니다. 일반적으로 함수 원형에 기본값을 지정하는 것이 권장됩니다.
이는 헤더 파일에 함수 원형을 선언할 때 기본값이 포함되어야 컴파일러가 함수 호출을 해석할 수 있기 때문입니다.
올바른 방법 (함수 원형에 기본값 지정)
// my_printer.h
#pragma once
#include <string>
// 함수 원형에 기본 매개변수 지정
void printData(int value, char separator = '-', int repeat = 1);
// my_printer.cpp
#include "my_printer.h"
#include <iostream>
// 함수 정의에는 기본 매개변수를 다시 지정하지 않음
void printData(int value, char separator, int repeat) {
for (int i = 0; i < repeat; ++i) {
std::cout << value;
if (i < repeat - 1) { // 마지막을 제외하고 구분자 출력
std::cout << separator;
}
}
std::cout << std::endl;
}
// main.cpp
#include "my_printer.h" // 원형이 있는 헤더 포함
int main() {
printData(10); // 10 (separator='-', repeat=1)
printData(20, '*'); // 20* (repeat=1)
printData(30, '#', 5); // 30#30#30#30#30
return 0;
}
기본 매개변수와 함수 오버로딩의 관계
기본 매개변수는 함수 오버로딩과 함께 사용될 때 모호성(Ambiguity) 을 유발할 수 있습니다.
컴파일러가 함수 호출에 대해 오버로딩된 여러 함수와 기본 매개변수를 가진 함수 중 어떤 것을 선택해야 할지 명확하지 않을 때 발생합니다.
#include <iostream>
#include <string>
void greet(std::string name) { // 오버로딩된 함수
std::cout << "안녕하세요, " << name << std::endl;
}
void greet(std::string name, std::string salutation = "안녕") { // 기본 매개변수를 가진 함수
std::cout << salutation << ", " << name << std::endl;
}
int main() {
// greet("홍길동"); // 컴파일 오류! 모호성 발생!
// greet(std::string)과 greet(std::string, std::string="안녕")
// 둘 다 greet("홍길동")에 매칭될 수 있기 때문
return 0;
}
위 예시에서 greet("홍길동")
을 호출하면, 컴파일러는 greet(std::string)
을 호출할지, 아니면 두 번째 greet
함수에서 salutation
매개변수에 기본값을 사용하여 greet(std::string, std::string)
을 호출할지 결정할 수 없습니다.
이러한 모호성을 피하려면,
- 기본 매개변수와 오버로딩된 함수들이 충돌하지 않도록 설계합니다.
- 모호성이 발생하면 명시적으로 원하는 함수를 호출하도록 인자를 모두 제공합니다.
결론: 기본 매개변수의 효율적인 활용
기본 매개변수는 함수의 유연성을 높이고 코드 중복을 줄이는 강력한 도구입니다.
특히 선택적인 인자를 가지는 함수나, 대부분의 경우 동일한 기본값을 사용하는 매개변수가 있을 때 매우 유용합니다.
하지만 올바른 위치에 선언하고, 함수 오버로딩과의 관계에서 발생할 수 있는 모호성에 주의해야 합니다.
현대 C++에서는 기본 매개변수를 사용하여 함수의 다양한 사용 시나리오를 간결하게 표현하는 것이 일반적인 관례입니다.