52. 생성자/소멸자 내부에서의 가상 함수 호출과 동적 타입의 변화

난이도 상 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C++
// 주제: 생성자/소멸자 내부에서의 가상 함수 호출과 동적 타입의 변화
//
// 과제:
//   1) 아래 프로그램의 출력을 예측하라. (특히 Base 생성자/소멸자 안에서 호출한
//      OnInit()/OnShutdown() 이 어느 클래스의 구현을 부르는지)
//   2) "가상 함수는 항상 최종 오버라이더가 호출된다"는 통념이 생성/소멸 중에는
//      왜 성립하지 않는지, 객체의 동적 타입이 생성/소멸 과정에서 어떻게 변하는지
//      내부 동작(vptr/vtable 관점)으로 설명하라.
//   3) 만약 OnInit() 이 순수 가상 함수(=0)였다면 Base 생성자에서의 호출은
//      어떻게 되는가?

#include <cstdio>

struct Base {
    Base()  { printf("Base()  -> "); OnInit(); }
    virtual ~Base() { printf("~Base() -> "); OnShutdown(); }

    virtual void OnInit()     { printf("Base::OnInit\n"); }
    virtual void OnShutdown() { printf("Base::OnShutdown\n"); }
};

struct Actor : Base {
    int* buffer_;
    Actor() : buffer_(new int[4]{}) { printf("Actor()\n"); }
    ~Actor() override { printf("~Actor()\n"); delete[] buffer_; }

    void OnInit()     override { printf("Actor::OnInit (buffer_=%p)\n", (void*)buffer_); }
    void OnShutdown() override { printf("Actor::OnShutdown\n"); }
};

int main() {
    printf("--- construct ---\n");
    Base* p = new Actor();
    printf("--- direct call ---\n");
    p->OnInit();
    printf("--- destruct ---\n");
    delete p;
    return 0;
}
내 리뷰 · C++
내 답안 · 자동 저장

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