1. 가상 소멸자(virtual destructor)와 다형적 삭제

난이도 중 해설 보기 →

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

결함 코드 · C++
// ============================================================================
// [언어 내부동작 문제] C++ - 가상 소멸자(virtual destructor)와 다형적 삭제
// ----------------------------------------------------------------------------
// 주제: 기반 클래스 포인터로 파생 객체를 delete 할 때 내부적으로 무슨 일이 일어나는가?
//   - 이 문제는 "결함을 고치는" 문제가 아니라, C++ 의 동작 원리를 설명하는 문제다.
//   - 게임서버에서 흔한 패턴: 기반 인터페이스 포인터(예: ISession*, IPacketHandler*,
//     IComponent*)로 파생 객체들을 보관/삭제한다.
//
// 과제:
//   1) 아래 main 의 출력(어떤 소멸자가 호출되는지, 순서)을 예측하라.
//   2) 그렇게 되는 이유를 vtable / 정적 vs 동적 타입 / 소멸자 호출 메커니즘 관점에서
//      내부적으로 설명하라.
//   3) Base 에 무엇을 추가하면 동작이 어떻게 바뀌는지, 그리고 그 비용(객체 크기/vptr)은
//      무엇인지 설명하라.
//   (먼저 직접 예측·설명을 적은 뒤 answer.md 와 대조할 것)
// ============================================================================

#include <cstdio>
#include <memory>

struct Resource {
    Resource()  { std::printf("Resource acquired\n"); }
    ~Resource() { std::printf("Resource released\n"); }
};

class Base {
public:
    Base()  { std::printf("Base()\n"); }
    ~Base() { std::printf("~Base()\n"); }     // (A) 소멸자 선언에 주목
};

class Derived : public Base {
public:
    Derived()  { std::printf("Derived()\n"); }
    ~Derived() { std::printf("~Derived()\n"); }
private:
    Resource res_;     // 파생 클래스가 소유하는 자원
};

int main() {
    Base* p = new Derived();   // (B) 정적 타입 Base*, 동적 타입 Derived
    delete p;                  // (B) 기반 포인터로 삭제

    // 참고: unique_ptr<Base> 로 보관해도 같은 질문이 성립한다.
    return 0;
}
내 리뷰 · C++
내 답안 · 자동 저장

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