Это дополнительный вопрос к: Почему dynamic_cast разрешено давать нулевой указатель для классов polymorphi c, когда целевой указатель не относится к типу базового класса? .
Стандарт C ++ 17 определяет dynamic_cast
в §8.2.7 [expr.dynami c .cast] .
§8.2.7 (1) состояния
Результатом выражения dynamic_cast<T>(v)
является результат преобразования выражения v в тип T. T должен быть указателем или ссылкой на полный тип класса, или «указатель на cv void». [...]
(2) определяет категории значений, (3) преобразование в cv для одного и того же типа и (4) случай nullptr
. Каждый второй абзац [expr.dynami c .cast] связан с полиморфными c типами в одной иерархии типов.
Я не знаю ни одного варианта использования для dynamic_cast
кроме приведения между типами внутри одной иерархии типов. С учетом следующих типов:
struct A
{
virtual ~A() = default;
};
struct B : A
{
virtual ~B() = default;
};
A*
можно привести к B*
, что, вероятно, является наиболее распространенным вариантом использования для dynamic_cast
:
A* ptr = new B;
dynamic_cast<B*>(ptr);
Я ожидаю этого компилировать, потому что B
и A
находятся в одной иерархии типов (B
является производным от A
). В хорошо определенной программе указатель типа A*
может указывать на объект типа B
.
Теперь давайте удалим базовый класс:
struct C
{
virtual ~C() = default;
};
struct D
{
virtual ~D() = default;
};
Удивительно, но dynamic_cast
все еще разрешено:
C* ptr;
dynamic_cast<D*>(ptr);
Я не вижу никакой причины, по которой такое приведение не могло быть неправильно сформировано (что приводило к ошибке компилятора). Насколько я знаю, в хорошо определенной программе нет никакого способа, которым ptr
может указывать на объект типа D
.
Почему разрешен такой бросок? Почему это не запрещено стандартом?