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++
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.