Я использовал шаблон CRTP некоторое время, однако, читая ответы о неопределенном поведении, связанном с понижением рейтинга, я не понимаю, почему static_cast<Derived&>(this)
, где this
имеет тип Base<Derived>*
, это определенное поведение, где Derived
публично наследуется от Base<Derived>
.
Стандарт совершенно ясен:
static_cast (выражение)
Если new_type является указателем или ссылкой нанекоторый класс D и тип выражения являются указателем или ссылкой на его не виртуальную базу B, static_cast выполняет downcast.Это понижение является неправильным, если B является неоднозначным, недоступным или виртуальным основанием (или основанием виртуального основания) D.
Но, глядя на аналогичные вопросы, C ++ наследование наследования :
Как выполнить приведение из точечного объекта [ Базовый класс ] к объекту подпункта [ Производный класс ]?
Самый рейтинговый ответ:
"Вы не можете; если только у точки [ База ] нет оператора преобразования или подпункта [ Производное ] имеет конструктор преобразования, и в этом случае типы объектов могут быть преобразованы без необходимости приведения. "
Другой пример: родительский класс static_cast для дочернего класса C ++
// B : public A
A a;
B* bptr = static_cast<B*>(&a);
Самый рейтинговый комментарий:
«Это неопределенное поведение».
Но затем говорит:
«Выможет сделать это безопасно, используя CRTP или dynamic_cast. "
Здесь ( C ++ static_cast downcast validity ) это снова упоминается:
Base base{190};
A& a = static_cast<A&>(base);
"Нет [недопустимо], объект типа Base не является объектом типа A [ Производное ]"
Чем отличается downcast в CRTP;почему это не вызывает неопределенное поведение, а случаи выше?Следуя логике ответа выше, не правда ли, что класс Base<Derived>
не является объектом типа Derived
(обратное утверждение верно), но вы можете использовать static_cast
?
ВозможноЯ просто неправильно понимаю CRTP.