Объяснение примера линеаризации иерархий классов Строструпа
В языке программирования Строструпа C++ (4-е изд.), раздел 27.4.2 показывает метод "линеаризации" иерархии классов diamond, чтобы избежать накладных расходов виртуальных базовых классов. Он начинает с алмазного узора из реального проекта (Pivot Code analyzer tool):

Линейный вариант рисуется следующим образом:

И

Схема кода такова:
namespace ipr {
struct Node { ... };
struct Expr : Node { ... };
struct Stmt : Expr { ... };
struct Decl : Stmt { ... };
struct Var : Decl { ... };
namespace impl {
template<class T> struct Node : T { ... };
template<class T> struct Expr : Node<T> { ... };
template<class S> struct Stmt : S { ... };
template<class D> struct Decl : Stmt<Expr<D>> { ... };
struct Var : Decl<ipr::Var> { ... };
}
}
Меня смущает нерегулярная структура. На основе начальное описание, я ожидал, что impl будет выглядеть примерно так:
namespace impl {
template<class T> struct Node : T { ... };
template<class T> struct Expr : Node<T> { ... };
template<class S> struct Stmt : Expr<S> { ... };
template<class D> struct Decl : Stmt<D> { ... };
struct Var : Decl<ipr::Var> { ... };
}
И я думаю, что полная диаграмма этих классов:

Мой вопрос: , почему "внутренние" три класса шаблонов impl не имеют параллельных форм, как в моей версии кода?
1 ответ:
Мое лучшее предположение исходит из того, что я смотрю на фактический сводный код , который имеет
template<class D> struct Decl : Stmt<Node<D>> { ... };Вместо Строструпа
Это предполагает, чтоtemplate<class D> struct Decl : Stmt<Expr<D>> { ... };impl::Stmtне обязательно выводится изimpl::Expr, как в исходной диаграмме алмаза (хотя она все еще выводится из интерфейсаipr::Expr). Он не является производным отimpl::ExprдляDeclиVar, но он делает это для других классов реализации, таких какimpl::For:struct For : Stmt<Expr<ipr::For> > { ... }Я не уверен, почему Страуструп не объяснить неровность. Возможно, он думал, что удалил его, изменив
Надеюсь, что лучший ответ объяснит это.Stmt<Node>наStmt<Expr>, или, возможно, он вообще не изменял его (то есть код изменился после того, как он скопировал его), и он хотел оставить его как есть, не объясняя каждую деталь.