5. 객체 슬라이싱(object slicing)과 가상 디스패치
난이도 중 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C++
// ============================================================================
// [언어 내부동작 문제] C++ - 객체 슬라이싱(object slicing)과 가상 디스패치
// ----------------------------------------------------------------------------
// 주제: 파생 객체를 "값"으로 기반 클래스에 복사할 때 일어나는 슬라이싱과, vptr/vtable
// 에 의한 가상 함수 디스패치가 어떻게 정해지는지.
//
// 아래는 몬스터 기반 클래스와 보스 파생 클래스다. 같은 객체를 참조/포인터/값/컨테이너로
// 다룰 때 hp() 가 어떤 구현으로 불리는지 묻는다.
//
// 과제(코드를 고치는 문제가 아니라, 출력과 내부 동작을 예측·설명하는 문제):
// 1) (2)(3)(4)(5) 각 줄의 출력값을 예측하라.
// 2) printHp(Monster m) 처럼 값으로 받을 때, m 의 동적 타입과 vptr 이 어떻게 되는지
// (왜 Boss::hp 가 불리지 않는지) vtable 관점에서 설명하라.
// 3) std::vector<Monster> 에 Boss 를 push_back 하면 무엇이 저장되는가? 슬라이싱을
// 피하려면 컨테이너/파라미터를 어떻게 설계해야 하는가?
// (먼저 직접 예측을 적은 뒤 answer.md 와 대조할 것)
// ============================================================================
#include <iostream>
#include <vector>
struct Monster {
virtual int hp() const { return 100; }
virtual ~Monster() = default;
};
struct Boss : Monster {
int extra = 500;
int hp() const override { return 100 + extra; } // 600
};
void printHp(Monster m) { // 값으로 받음
std::cout << "printHp: " << m.hp() << "\n"; // (4)
}
int main() {
Boss b;
Monster& ref = b;
std::cout << "ref: " << ref.hp() << "\n"; // (2)
Monster* ptr = &b;
std::cout << "ptr: " << ptr->hp() << "\n"; // (3)
printHp(b); // (4) 값 전달
std::vector<Monster> v;
v.push_back(b); // 컨테이너에 값 저장
std::cout << "vec: " << v[0].hp() << "\n"; // (5)
return 0;
} 내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.