Рассмотрим эту иерархию классов:
struct Animal { virtual ~Animal(); };
struct Cat : virtual Animal {};
struct Dog final : virtual Animal {};
Я понимаю, что размещение final
на class Dog
гарантирует, что никто не сможет создать класс, наследующий от Dog
, что, в свою очередь, означает, что никто не может создать класс, который IS-A Dog
и IS -A Cat
.
Рассмотрим эти два dynamic_cast
s:
Dog *to_final(Cat *c) {
return dynamic_cast<Dog*>(c);
}
Cat *from_final(Dog *d) {
return dynamic_cast<Cat*>(d);
}
GCC, ICC и MSVC игнорируют квалификатор final
и генерируют вызов __dynamic_cast
; это несчастливо, но не удивительно.
Что меня удивило, так это то, что Clang и Zapcc генерируют оптимальный код для from_final
( "always return nullptr" ), но генерируют вызов до __dynamic_cast
для to_final
.
Является ли это действительно упущенной возможностью оптимизации (в компиляторе, где, очевидно, кто-то приложил некоторые усилия для соблюдения квалификатора final
в приведениях) или оптимизация невозможна в этом случае по какой-то тонкой причине, что я все еще не вижу