Когда ты кидаешь исключение через параметр-ссылку, C++ кидает объект на основе статического типа выражения, а не его runtime типа. Это значит, что если ты кидаешь ссылку на базовый класс, ты кидаешь объект базового класса — даже если на самом деле это объект производного класса.
void f(MyExceptionBase& e) {
throw e; // Кидает MyExceptionBase, не derived тип
}
Из-за этого catch-блок для производного класса пропускается, и ловится только базовое исключение.
raise()Рекомендуемый подход — использовать виртуальную функцию, чтобы отложить throw до момента, когда доступна информация о runtime типе:
class MyExceptionBase {
public:
virtual void raise() {
throw *this;
}
};
class MyExceptionDerived : public MyExceptionBase {
public:
void raise() override {
throw *this;
}
};
e.raise() вместо прямого throwraise() виртуальный, вызывается правильный метод производного классаMyExceptionDerived::raise() статический тип — это MyExceptionDerivedthrow *this корректно кидает исключение производного типаvoid f(MyExceptionBase& e) {
e.raise(); // Полиморфное поведение достигнуто
}
Этот паттерн гарантирует, что исключения, кинутые через ссылки на базовый класс, сохраняют свой реальный тип, что позволяет корректно работать полиморфной обработке исключений и правильно подбирать catch-блоки.
Когда ты бросаешь исключение через ссылку на базовый класс, C++ использует статический тип ссылки для определения того, какой объект исключения выбросить, независимо от фактического типа объекта во время выполнения.
Новый — ещё не проверен сообществом
Вы