23. 이름 숨김(name hiding)과 오버로드 해석의 스코프 규칙
난이도 최상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C++
// ============================================================================
// [언어 내부동작 문제] C++ - 이름 숨김(name hiding)과 오버로드 해석의 스코프 규칙
// ----------------------------------------------------------------------------
// 주제: 파생 클래스에서 기반 클래스와 "같은 이름"의 함수를 새로 선언하면,
// 기반 클래스에 있던 그 이름의 오버로드들은 어떻게 되는가?
// - 이 문제는 "결함을 고치는" 문제가 아니라, C++ 의 동작 원리를 설명하는 문제다.
// - 게임서버 코드에서 흔한 패턴: 기반 패킷 핸들러 클래스에 Handle(int), Handle(const char*)
// 같은 오버로드를 두고, 파생 클래스가 특정 타입만 재정의(오버라이드/오버로드)하려 한다.
//
// 과제:
// 1) 아래 main 의 각 호출이 컴파일되는지, 컴파일된다면 어떤 함수가 호출되는지 예측하라.
// 컴파일 에러가 나는 줄이 있다면 어떤 줄이고 왜인지 예측하라.
// 2) C++ 이름 조회(name lookup)가 "스코프 단위로 멈춘다"는 것이 무슨 뜻인지,
// 이것이 오버로드 해석(인자 타입 매칭)보다 왜 먼저 일어나는지 설명하라.
// 3) (A) 지점에 무엇을 추가하면 기반 클래스의 오버로드들이 다시 보이게 되는지,
// 그리고 그 메커니즘이 내부적으로 무엇을 하는 것인지 설명하라.
// 4) 이 규칙이 가상 함수 오버라이딩(시그니처가 정확히 같은 경우)과는 어떻게 다르게
// 상호작용하는지 설명하라.
// (먼저 직접 예측·설명을 적은 뒤 answer.md 와 대조할 것)
// ============================================================================
#include <cstdio>
class PacketHandlerBase {
public:
virtual ~PacketHandlerBase() = default;
void Handle(int code) {
std::printf("Base::Handle(int) code=%d\n", code);
}
void Handle(const char* name) {
std::printf("Base::Handle(const char*) name=%s\n", name);
}
virtual void Handle(double value) {
std::printf("Base::Handle(double) value=%.1f\n", value);
}
};
class LoginHandler : public PacketHandlerBase {
public:
// (A) 여기에 기반 클래스의 오버로드 세트를 다시 끌어오지 않았다.
// Base::Handle(int) 와 Base::Handle(const char*) 는 어떻게 되는가?
void Handle(int code) { // 시그니처가 Base::Handle(int) 와 동일하지만 virtual 아님
std::printf("LoginHandler::Handle(int) code=%d\n", code);
}
void Handle(double value) override { // 진짜 가상 오버라이드
std::printf("LoginHandler::Handle(double) value=%.1f\n", value);
}
};
int main() {
LoginHandler lh;
lh.Handle(42); // 어떤 Handle 이 호출되는가?
lh.Handle(3.14); // 어떤 Handle 이 호출되는가?
// lh.Handle("ping"); // 이 줄의 주석을 풀면 무슨 일이 일어나는가? (컴파일 여부 예측)
PacketHandlerBase* base = &lh;
base->Handle(42); // 정적 타입 기준 오버로드 해석 + 동적 디스패치, 무엇이 출력되는가?
base->Handle(3.14);
return 0;
} 내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.