c++ - учебник - html и xhtml. подробное руководство скачать




Неправильный листинг-это листинг или использование, которое является неопределенным поведением (2)

Само литье имеет неопределенное поведение. Цитирование C ++ 17 (n4659) [expr.static.cast] 8.2.10 / 11:

PRvalue типа «указатель на cv1 B », где B является типом класса, может быть преобразовано в prvalue типа «указатель на cv2 D », где D - это производный класс (раздел 13) из B , если cv2 является такая же CV -квалификация, как или более высокая cv-квалификация, чем cv1 . ... Если prvalue типа «указатель на cv1 B » указывает на B который на самом деле является подобъектом объекта типа D , результирующий указатель указывает на охватывающий объект типа D В противном случае поведение не определено.

Если я делаю приведение из базового типа в производный, но базовый тип не является экземпляром производного типа, но только использует результат, если он есть, я получаю неопределенное поведение?

Трудно понять, что я спрашиваю? взгляните на этот пример:

struct Animal { int GetType(){...} };
struct Dog : Animal { bool HasLoudBark(){...}};
struct Cat : Animal { bool HasEvilStare(){...} };

Animal * a = ...;
Dog* d = static_cast<Dog*>(a);

if(a->GetType() == DogType && d->HasLoudBark())
    ....

В этом случае Dog может быть или не быть. Мы всегда делаем static_cast of a для Dog * d но мы никогда не используем d если мы не уверены в его Dog .

Предполагая, что a не является Dog , это неопределенное поведение в точке броска? Или это определяется так, как мы фактически не используем d если это действительно не Dog ?

Приветствуются ссылки на соответствующие части стандарта.

(Да, я знаю, что могу использовать dynamic_cast и RTTI, и, вероятно, это не отличный код, но меня больше интересует, действительно ли это)


Это неопределенное поведение, но если бы вы использовали reinterpret_cast вместо static_cast , вы бы отбросили этого демона.

[expr.reinterpret.cast]/7

Указатель объекта может быть явно преобразован в указатель объекта другого типа. Когда prvalue v типа указателя объекта преобразуется в тип указателя объекта «указатель на cv T », результатом является static_cast<cv T*>(static_cast<cv void*>(v)) .

Как отметил пользователь Angew, для этого требуется определенное внутреннее представление, которое гарантирует, что static_cast<void*>(d) == static_cast<void*>(a) когда a == d ". Эти требования выполняются при работе с простым наследованием и объектами с выравниванием по умолчанию.





undefined-behavior