Следующий код об обработке исключений. Я получил вывод:
Botch::f()
I'll be back!
Почему фрукты не поймали? Спасибо!
Проигнорируйте это. Я думаю, что предоставил достаточно деталей.
#include <exception>
#include <iostream>
using namespace std;
void terminator() {
cout << "I'll be back!" << endl;
exit(0);
}
void (*old_terminate)() = set_terminate(terminator);
class Fruit {};
class Botch {
public:
void f() throw(Fruit, bad_exception) {
cout << "Botch::f()" << endl;
throw Fruit();
}
~Botch() { throw 'c'; }
};
int main() {
try{
Botch b;
b.f();
} catch(Fruit&) {
cout << "inside catch(Fruit)" << endl;
} catch(bad_exception&) {
cout << "caught a bad_excpetionfrom f" << endl;
}
}
Fruit
не перехватывается, потому что код никогда не достигает этого предложения catch. в try
блокировать в main
Призыв к b.f()
выдает исключение типа Fruit
, В ответ код уничтожает Botch
перед входом в предложение catch. Деструктор Botch
выдает еще одно исключение, и это вызывает вызов terminate
,
Потому что во время разматывания стека для вашего исключения Fruit вы бросили другое исключение (из Botch
деструктор). Таким образом, ваш терминатор был назван вместо. Вот почему выбрасывать исключения из деструктора — плохая идея,
когда b.f()
называется в основном Fruit
брошен Затем исполнение покидает try
блок, и до того, как любой обработчик catch может поймать это Fruit
, b
разрушен и 'c'
брошен Бросив второе исключение, пока Fruit
все еще активный приводит к завершению, независимо от каких-либо обработчиков перехвата.
Это причина, почему вы никогда не будете бросать из деструкторов.
потому что поток программы выглядит следующим образом:
try{
Botch b;
b.f();
//-> exception of class Fruit has been thrown
//-> Stack unwinding: during stack unwinding object b,
//which is on stack is destroyed, and its destructor is called
//-> this destructor ~Botch() { throw 'c'; } throws another exception
//and this caused call of your terminator()
} catch(Fruit&) { // so we are never here