В первый раз я подумал, что этот код не будет скомпилирован, потому что std :: nested_exception не является производным от std :: exception
Этого недостаточно - std::nested_exception
предназначен для использования в качестве класса mixin, например
struct MyExceptionWrapper: public std::exception, std::nested_exception
{
// an 3rd-party component of my library threw
// and I want to wrap it with a common interface
};
ожидал, что dynamic_cast сделает статическую проверку наследования, но я ошибся
В приведенном выше случае dynamic_cast
должен проверить во время выполнения , является ли ваш std::exception
действительно a MyExceptionWrapper
, в этом случае также a std::nested_exception
.
Вот почему он называется dynamic cast, потому что он должен проверять динамический тип во время выполнения. Если вы хотите выполнить статическую проверку во время компиляции, вы ищете static cast.
Хотя я не смог найти соответствующую стандартную спецификацию, которая явно упоминает, что dynamic_cast позволяет это
Это все хорошо документировано . Мы обсуждаем следующий пункт со связанной страницы:
- 5) Если выражение является указателем или ссылкой на полиморфный тип Base, а new_type является указателем или ссылкой на тип Производный, выполняется проверка во время выполнения:
(обратите внимание, что Base=std::exception
является полиморфным)
- b) В противном случае, если выражение указывает / относится к общедоступной базе самого производного объекта и, одновременно, самый производный объект имеет однозначный общедоступный базовый класс типа Derived, результат приведения точек / относится к этому Производное (это называется «sidecast».)
Поскольку вы не можете сказать во время компиляции, что std::exception&
на самом деле не MyExceptionWrapper
, вы должны сделать это во время выполнения.
PS. если вы хотите избежать случайной переброски внутри блока catch
, просто напишите
auto *nested = dynamic_cast<std::nested_exception*>(&e);
вместо этого. Затем вы можете проверить на nullptr
, чтобы выяснить, удалось ли это.
PPS. Как предполагает Шон, MyExceptionWrapper
выше, скорее всего, будет типом, сгенерированным throw_with_nested
, но он имеет тот же эффект.