20. RTTI: dynamic_cast / typeid 의 내부 동작
난이도 상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C++
// [주제] RTTI: dynamic_cast 와 typeid 의 내부 동작
// 다형적 타입(가상 함수를 가진 타입)은 vtable 을 통해 실행 시점의 "실제 타입"
// 정보를 참조할 수 있다. 아래 프로그램은 typeid 와 dynamic_cast 를 여러
// 상황(다운캐스트 성공/실패, 참조 캐스트, 형제 베이스 간 cross-cast,
// dynamic_cast<void*>, 비다형 타입)에서 사용한다.
//
// [과제]
// 1) 출력 라인 1~8 이 각각 무엇을 출력할지 예측하라.
// 2) typeid(*e) 가 어떻게 런타임 실제 타입을 알아내는지, dynamic_cast 의
// 포인터 실패와 참조 실패가 어떻게 다르게 표현되는지, 형제 베이스 간
// cross-cast 와 dynamic_cast<void*> 가 무엇을 돌려주는지, 그리고
// 비다형 타입에서 typeid 가 어떻게 처리되는지 내부 동작(vtable /
// type_info / 포인터 보정)으로 설명하라.
// (내부 동작 설명은 answer.md 참조 — 먼저 스스로 예측/설명해 볼 것.)
#include <iostream>
#include <typeinfo>
struct Entity { virtual ~Entity() {} };
struct Character : Entity { int hp = 100; };
struct Monster : Entity { int atk = 7; };
struct Boss : Monster { int phase = 2; };
struct Renderable { virtual ~Renderable() {} };
struct Collidable { virtual ~Collidable() {} };
struct GameObject : Renderable, Collidable { };
struct NonPoly { int x; }; // 가상 함수 없음(비다형)
int main() {
Entity* e = new Boss();
std::cout << "1: " << (typeid(*e) == typeid(Boss)) << "\n";
std::cout << "2: " << (typeid(*e) == typeid(Monster)) << "\n";
Monster* m = dynamic_cast<Monster*>(e);
std::cout << "3: " << (m != nullptr) << "\n";
Character* c = dynamic_cast<Character*>(e);
std::cout << "4: " << (c != nullptr) << "\n";
void* most = dynamic_cast<void*>(e);
std::cout << "5: " << (most == static_cast<void*>(static_cast<Boss*>(e))) << "\n";
try {
Character& cr = dynamic_cast<Character&>(*e);
(void)cr;
std::cout << "6: no throw\n";
} catch (const std::bad_cast&) {
std::cout << "6: bad_cast\n";
}
Renderable* r = new GameObject();
Collidable* col = dynamic_cast<Collidable*>(r); // 형제 베이스 간 cross-cast
std::cout << "7: " << (col != nullptr) << "\n";
NonPoly np; NonPoly* npp = &np;
std::cout << "8: " << (typeid(*npp) == typeid(NonPoly)) << "\n";
delete e;
delete r;
return 0;
} 내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.