Чтобы уточнить ответ Нейла:
throw;
сама попытается повторно поднять текущее исключение, которое было отменено - если несколько раз отменяется, оно пытается сбросить самое последнее. Если ни один из них не был размотан, вызывается метод terminate (), сигнализирующий, что ваша программа сделала что-то поддельное.
Что касается вашего следующего вопроса, почему компилятор не предупреждает с помощью throw;
вне блока catch, это то, что компилятор не может сказать во время компиляции, может ли строка throw;
выполняться в контексте блок улова. Рассмотрим:
// you can try executing this code on [http://codepad.org/pZv9VgiX][1]
#include <iostream>
using namespace std;
void f() {
throw 1;
}
void g() {
// will look at int and char exceptions
try {
throw;
} catch (int xyz){
cout << "caught int " << xyz << "\n";
} catch (char xyz){
cout << "caught char " << xyz << "\n";
}
}
void h() {
try {
f();
} catch (...) {
// use g as a common exception filter
g();
}
}
int main(){
try {
h();
} catch (...) {
cout << "some other exception.\n";
}
}
В этой программе g()
работает как фильтр исключений и может использоваться из h()
и любой другой функции, которая может использовать это поведение обработки исключений. Вы даже можете представить себе более сложные случаи:
void attempt_recovery() {
try{
// do stuff
return;
} catch (...) {}
// throw original exception cause
throw;
}
void do_something() {
for(;;) {
try {
// do stuff
} catch (...) {
attempt_recovery();
}
}
}
Здесь, если в do_something происходит исключение, будет вызван код восстановления. Если этот код восстановления завершится успешно, исходное исключение будет забыто и задача будет повторена. В случае сбоя кода восстановления этот сбой игнорируется, а предыдущий сбрасывается повторно. Это работает, потому что throw;
в attempt_recovery
вызывается в контексте блока catch do_something
.