16. CRTP와 정적 다형성(static polymorphism)

난이도 중 해설 보기 →

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

결함 코드 · C++
// 주제: CRTP(Curiously Recurring Template Pattern)와 정적 다형성(static polymorphism).
//
// 아래 Shape<Derived> 는 가상 함수 없이, 자기 자신을 템플릿 인자로 받은 파생 타입으로
// static_cast 해 파생의 구현(drawImpl/areaImpl)을 호출한다. render() 도 가상 디스패치가
// 아니라 템플릿으로 각 타입에 대해 인스턴스화된다.
//
// 과제:
//   1) 이 프로그램의 정확한 표준출력을 예측하라(특히 sizeof 두 값과 area 두 값).
//   2) 가상 함수가 하나도 없는데 어떻게 "파생별로 다른 동작"이 선택되는지(디스패치가
//      언제 결정되는지) 내부 동작을 설명하라.
//   3) sizeof(Circle)/sizeof(Square) 가 그 값이 나오는 이유를 설명하라.
//   4) 런타임 가상 함수(vtable) 다형성과 비교해 장단점을 설명하라.

#include <cstdio>

template <class Derived>
struct Shape {
    void   draw() const { static_cast<const Derived*>(this)->drawImpl(); }
    double area() const { return static_cast<const Derived*>(this)->areaImpl(); }
};

struct Circle : Shape<Circle> {
    double r;
    explicit Circle(double r_) : r(r_) {}
    void   drawImpl() const { std::printf("Circle r=%.1f\n", r); }
    double areaImpl() const { return 3.14159 * r * r; }
};

struct Square : Shape<Square> {
    double s;
    explicit Square(double s_) : s(s_) {}
    void   drawImpl() const { std::printf("Square s=%.1f\n", s); }
    double areaImpl() const { return s * s; }
};

template <class D>
void render(const Shape<D>& sh) { sh.draw(); }   // 컴파일 타임에 D별로 인스턴스화

int main() {
    Circle c(2.0);
    Square q(3.0);
    render(c);
    render(q);
    std::printf("sizeof(Circle)=%zu sizeof(Square)=%zu\n", sizeof(Circle), sizeof(Square));
    std::printf("areas: %.2f %.2f\n", c.area(), q.area());
    return 0;
}
내 리뷰 · C++
내 답안 · 자동 저장

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