Static_cast vs dynamic_cast

Предположим, что мне предоставлена ​​библиотека С++, полная наследования. Мне предоставляется функция Base* в функции, когда я знаю, что она фактически указывает на объект Derived и Derived наследует Base. Но я не знаю, какое это наследство (public/protected/private). Я также не знаю, есть ли виртуальная функция в иерархии.

Учитывая эту ситуацию, , не глядя на исходный код/​​документацию из Base и Derived, какой листинг следует использовать? Или я должен сначала проконсультироваться с кодом/документацией, чтобы убедиться в полиморфизме?

Фон

Я пишу changeEvent функцию QMainWindow в Qt 4.7. Функция changeEvent принимает QEvent*, которую я могу передать другому типу, зная QEvent::type(). Мне было интересно, следует ли использовать static_cast или dynamic_cast.

Спасибо.

Ответ 1

Используйте static_cast. Если вы знаете, что ваш Base* указывает на Derived, используйте static_cast. dynamic_cast полезен, когда он может указывать на производный.

Ответ 2

Если вы сомневаетесь, вы должны предпочесть dynamic_cast. Это может быть медленнее, но вы, вероятно, не заметите разницу.

Если вам нужна скорость, используйте следующий фрагмент:

template <typename Derived, typename Base>
Derived safe_static_cast(Base b)
{
  assert((void*)dynamic_cast<Derived>(b) && "safe_static_cast failed!");
  return static_cast<Derived>(b);
}

Или что-то эквивалентное.

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

Ответ 3

От MSDN -

В общем случае вы используете static_cast, когда хотите преобразовать числовые типы данных, такие как перечисления в int или ints, в float, и вы уверены в типах данных, участвующих в преобразовании. Преобразования static_cast не так безопасны, как преобразования dynamic_cast, потому что static_cast не проверяет тип выполнения во время выполнения, а dynamic_cast. Ошибка dynamic_cast для двусмысленного указателя не будет выполнена, а static_cast вернется, как будто ничего не случилось; это может быть опасно. Хотя конверсии dynamic_cast более безопасны, dynamic_cast работает только с указателями или ссылками, а проверка типа времени выполнения является накладными расходами.

Для получения дополнительной информации ознакомьтесь с этой ссылкой