31. 다중 상속의 객체 레이아웃과 this 포인터 조정(pointer adjustment)

난이도 최상 해설 보기 →

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

결함 코드 · C++
// 주제: 다중 상속의 객체 메모리 레이아웃과 this 포인터 조정(pointer adjustment)
//
// 과제:
//  1) 아래 프로그램의 출력(각 비교/오프셋 값)을 예측하라.
//  2) C 객체 안에서 A 서브오브젝트와 B 서브오브젝트가 어디에 놓이는지, 왜 A* 로의
//     캐스팅은 주소가 그대로이고 B* 로의 캐스팅은 주소가 이동하는지 설명하라.
//  3) static_cast 와 reinterpret_cast 의 차이(this 조정 수행 여부), 그리고 가상 함수
//     호출 시 thunk 가 왜 필요한지 설명하라. (설명은 answer.md 에)

#include <iostream>

struct A { int a = 1; virtual void fa() { std::cout << "A::fa\n"; } };
struct B { int b = 2; virtual void fb() { std::cout << "B::fb\n"; } };
struct C : A, B {
    int c = 3;
    void fa() override { std::cout << "C::fa\n"; }
    void fb() override { std::cout << "C::fb\n"; }
};

int main() {
    C obj;
    C* pc = &obj;
    A* pa = pc;                        // A* 로 업캐스트
    B* pb = pc;                        // B* 로 업캐스트

    std::cout << (static_cast<void*>(pa) == static_cast<void*>(pc)) << "\n"; // ?
    std::cout << (static_cast<void*>(pb) == static_cast<void*>(pc)) << "\n"; // ?
    std::cout << ((char*)pb - (char*)pc) << "\n";                            // B 서브오브젝트 오프셋

    B* pbBad = reinterpret_cast<B*>(pc); // reinterpret_cast
    std::cout << (pbBad == pb) << "\n";  // ?

    pb->fb();                            // pb->fb() 호출
    return 0;
}
내 리뷰 · C++
내 답안 · 자동 저장

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