C++ Default Parameter - 6. 특수한 상황에서의 Default Parameter 활용
2025. 3. 27. 15:50ㆍ프로그래밍 언어/C++
✅ 6. 특수한 상황에서의 Default Parameter 활용
📌 1. 템플릿 함수에서 기본 인자 사용
템플릿 함수에서도 일반 함수처럼 기본 인자를 지정할 수 있습니다.
단, 기본값은 컴파일 타임에 평가 가능해야 하며, 타입 유추와의 충돌에 주의해야 합니다.
✅ 함수 매개변수에 기본값 지정
template <typename T>
T multiply(T a, T b = T(1)) {
return a * b;
}
multiply(5); // b = 1
multiply(5, 2); // b = 2
✅ 템플릿 매개변수 자체에 기본값 지정
template <typename T = int>
T identity(T value = 0) {
return value;
}
identity(); // T = int, value = 0
identity(3.14); // T = double, value = 3.14
구분 | 예시 | 설명 |
템플릿 인자 | template <typename T = int> | 타입 자체의 기본값 |
함수 인자 | int func(int x = 10) | 값 자체의 기본값 |
📌 2. CRTP(Curiously Recurring Template Pattern)에서 기본 인자 활용
CRTP는 상위 템플릿 클래스에 하위 클래스 자신을 전달하여 상속 구조를 만드는 패턴입니다.
이 구조에서 기본 인자는 공통 동작의 유연성을 높이는 데 활용됩니다.
✅ 예시
template <typename Derived>
class Base {
public:
void execute(int repeat = 1) {
for (int i = 0; i < repeat; ++i) {
static_cast<Derived*>(this)->run();
}
}
};
class Worker : public Base<Worker> {
public:
void run() {
std::cout << "Working...\n";
}
};
Worker w;
w.execute(); // 기본값 repeat = 1
w.execute(3); // 3회 반복 실행
✅ 기본 인자를 통해 실행 횟수, 로그 수준 등 공통 제어가 가능
✅ 하위 클래스는 핵심 동작만 정의하면 됨 → 코드 재사용에 유리
📌 3. 클래스 멤버 함수에서 기본 인자 지정
클래스의 멤버 함수도 기본 인자를 사용할 수 있으며, 선언부에만 작성하는 것이 원칙입니다.
class Logger {
public:
void log(std::string msg = "Default message");
};
void Logger::log(std::string msg) {
std::cout << msg << '\n';
}
- 선언부와 정의부가 분리될 경우, 정의부에는 기본값을 쓰지 않아야 중복 정의 문제가 발생하지 않습니다.
📌 4. 가상 함수에서 기본 인자 사용 시 주의점
기본 인자는 정적 바인딩, 가상 함수 호출은 동적 바인딩을 따릅니다.
이로 인해 함수는 자식 클래스 것이 호출되더라도, 기본값은 부모 클래스 기준으로 적용됩니다.
❌ 잘못된 예시
class Base {
public:
virtual void greet(std::string name = "Base") {
std::cout << "Hello, " << name << '\n';
}
};
class Derived : public Base {
public:
void greet(std::string name = "Derived") override {
std::cout << "Hi, " << name << '\n';
}
};
Base* obj = new Derived();
obj->greet(); // 출력: Hi, Base ← 기본값은 Base 기준
✅ 해결 방법 ①: 기본 인자 제거 + 내부 처리
class Derived : public Base {
public:
void greet(std::string name) override {
if (name.empty()) name = "Derived";
std::cout << "Hi, " << name << '\n';
}
};
Derived d;
d.greet(""); // → Hi, Derived
✅ 해결 방법 ②: 비가상 래퍼 함수 사용
class Base {
public:
void greetWrapper(std::string name = "Base") {
greet(name);
}
virtual void greet(std::string name) {
std::cout << "Hello, " << name << '\n';
}
};
✅ 기본 인자는 비가상 함수에만 두고,
✅ 실제 동작은 가상 함수에서 처리 → 의도한 바인딩과 값 적용이 모두 보장
📌 5. static 멤버 함수에서 기본 인자
정적(static) 멤버 함수는 객체 없이 클래스 이름으로 호출되며,
기본 인자 사용에 아무런 제한이 없습니다.
class Settings {
public:
static void reset(int level = 1) {
std::cout << "Resetting to level " << level << '\n';
}
};
Settings::reset(); // 기본값 사용 → 1
Settings::reset(5); // 명시적 값 전달
- 가상 함수 아님 → 바인딩 문제 없음
- 일반 함수와 동일한 방식으로 활용 가능
📌 핵심 요약표
항목 | 설명 |
템플릿 인자 vs 함수 인자 | 타입과 값의 기본값을 구분해서 사용 |
CRTP와 기본 인자 활용 | 반복 제어, 옵션 전달 등 공통 로직 구성 가능 |
클래스 멤버 함수 | 선언부에만 기본 인자 작성 (정의부 생략) |
가상 함수와 기본 인자 | 기본 인자는 정적 타입 기준 → 동작 혼란 가능성 있음 |
가상 함수 해결 방법 | 기본 인자 제거 후 내부 처리 or 비가상 래퍼 함수 사용 |
static 멤버 함수와 기본 인자 | 일반 함수처럼 자유롭게 사용 가능 |
'프로그래밍 언어 > C++' 카테고리의 다른 글
C++ Default Parameter - 8. 최신 표준(C++11 이후)의 변화 (0) | 2025.03.27 |
---|---|
C++ Default Parameter - 7. 실전 예제 및 활용 사례 (0) | 2025.03.27 |
C++ Default Parameter - 5. 주의사항 및 Best Practice (0) | 2025.03.27 |
C++ Default Parameter - 4. Default Parameter와 함수 오버로딩 (0) | 2025.03.27 |
C++ Default Parameter - 3. Default Parameter의 동작 원리 (0) | 2025.03.27 |