Этот вопрос вдохновлен комментариями здесь.
Рассмотрим следующий фрагмент кода:
struct X {}; // no virtual members
struct Y : X {}; // may or may not have virtual members, doesn't matter
Y* func(X* x) { return dynamic_cast<Y*>(x); }
Несколько человек предложили, чтобы их компилятор отклонил тело func
.
Однако мне кажется, что независимо от того, определяется ли это стандартом, зависит от времени выполнения x
. Из раздела 5.2.7 ([expr.dynamic.cast]
):
Результат выражения
dynamic_cast<T>(v)
является результатом преобразуя выражениеv
в типT
.T
должен быть указателем или ссылку на полный тип класса или "указатель на cvvoid
". Операторdynamic_cast
не должен отбрасывать константу.Если
T
- тип указателя,v
должен быть prvalue указателя на полный класс type, а результатом является значение типаT
. ЕслиT
- значение l ссылочный типv
должен быть lvalue полного типа класса, а результатом является l-значение типа, обозначаемогоT
. ЕслиT
- значение r ссылочный типv
должен быть выражением, имеющим полный тип класса, и результатом является x значение типа, на которое указываетT
.Если тип
v
совпадает сT
, или он совпадает сT
, за исключением того, что тип объекта класса вT
больше CV, чем тип объекта класса вv
результатv
(при необходимости преобразуется).Если значение
v
является значением нулевого указателя в случае указателя, результатом является значение нулевого указателя типаT
.Если T является "указателем на cv1
B
" иv
имеет тип 'указатель на cv2D
", так чтоB
является базовым классомD
, результатом является указатель на уникальный объектB
объектаD
, на который указываетv
. Аналогично, если T является" ссылкой на cv1B
" иv
имеет тип cv2D
такой, чтоB
является базовым классомD
, результатом является единственный подобъектB
D
объект, на который ссылаетсяv
. Результатом является lvalue, еслиT
- значение lvalue reference или xvalue, еслиT
является ссылкой rvalue. Как в указатель и справочные случаи, программа плохо сформирована, если cv2 имеет более высокая cv-квалификация, чем cv1, или еслиB
является недоступным или неоднозначный базовый классD
.В противном случае
v
должен быть указателем на или значением полиморфного типа.Если
T
"указатель на cvvoid
", то результатом является указатель на наиболее производные объект, на который указываетv
. В противном случае применяется проверка времени выполнения для просмотра если объект, указанный или обозначенныйv
, может быть преобразован в тип указана или упомянутаT
.) Самый производный объект указал или ссылается наv
, может содержать другие объектыB
в качестве базовых классов, но они игнорируются.Если
C
- тип класса, к которому указывает или ссылаетсяT
проверка выполнения выполняется логически следующим образом:
Если, в большинстве случаев производный объект, на который указывает (обозначается) на
v
,v
указывает (ссылается) наpublic
подобъект базового класса объектаC
, и если только один объект типC
выводится из подобъекта, на который указывает (называется), наv
(указывает) на этот объектC
.В противном случае, если
v
указывает (ссылается) на подбобку базового классаpublic
самого производного объекта, и тип самого производного объекта имеет базовый класс, типC
, это однозначно иpublic
, точки результата (относится) кC
подобъектом самого производного объекта.В противном случае проверка времени выполнения выходит из строя.
Значение неудачного нажатия на тип указателя является нулевым значение указателя требуемого типа результата. Неудачное приведение к ссылке type throws
std::bad_cast
.
Как я читал это, требование полиморфного типа применяется только в том случае, если ни одно из вышеперечисленных условий не выполняется, и одно из этих условий зависит от значения времени выполнения.
Конечно, в некоторых случаях компилятор может положительно определить, что вход не может быть должным образом NULL (например, когда это указатель this
), но я все же думаю, что компилятор не может отклонить код, если он не может определить что утверждение будет достигнуто (обычно это вопрос времени выполнения).
Конечно, здесь важна диагностическая диагностика, но совместимо ли это стандартное для компилятора отклонение этого кода с ошибкой?