2010-08-24 2 views
5

Wenn ich einen Code wie den folgenden haben:Wird C++ ohne Argumente in einem anderen Frame arbeiten, um eine Exception erneut auszulösen?

try { 
    doSomething(); 
} catch (...) { 
    noteError(); 
} 

void noteError() { 
    try { 
    throw; 
    } catch (std::exception &err) { 
    std::cerr << "Note known error here: " << err.what(); 
    } catch (...) { 
    std::cerr << "Note unknown error here."; 
    } 
    throw; 
} 

Werden die ursprünglichen Ausnahmen von beiden Orten innerhalb des unteren Rahmens von noteError geworfen get()?

+1

Versuchen Sie es und sehen? Mein Verdacht ist, dass es nicht einmal kompilieren wird, aber ich verabscheue Ausnahmen, weiß also nicht wirklich. –

+5

@Dash, "versuche es und sehe" liefert nicht immer eine gültige und sichere Antwort. Vielleicht ist es ein undefiniertes Verhalten, und wenn du es versuchst, beweist es nur, dass es auf deiner Maschine und nirgendwo sonst funktioniert. Oder, wenn es fehlschlägt, liegt es vielleicht an einem Compilerfehler, der diesen bestimmten Aspekt des Standards nicht implementiert hat. –

+0

@Rob guter Punkt, danke. "Probieren Sie es aus und sehen Sie sich alle Compiler an, die Sie finden können, und fügen Sie dann den Comeau-Online-Compiler an den Anfang dieser Liste"? :) –

Antwort

4

Die Formulierung in der Norm (§ 15.1/2) (Hervorhebung von mir):

Wenn eine Ausnahme ausgelöst wird, die Steuerung an den nächsten Handler mit einem passenden Typ (15.3) übertragen wird; "Nearest" bedeutet den Handler, für den die zusammengesetzte Anweisung, ctor-initializer oder function-body nach dem try-Schlüsselwort zuletzt vom Thread der Steuerung eingegeben und noch nicht verlassen wurde.

Wann hat ein try Block "exited"? Gemäß der Grammatik (§15/1) enden try-Blöcke mit einer Sequenz von Handlern, so dass der Block endet, wenn der letzte Handler endet. Mit anderen Worten:

try // <- start of try block 
{ 
} 
catch (whatever) // <- first handler 
{ 
} 
// ... more handlers 
catch (whatever_again) // <- last handler 
{ 
} // <- end of try block 

Also ja, Ihr Code ist in Ordnung. Wenn er erneut geworfen wird, hat der nächste try-Block einen passenden Handler (nämlich), so dass der Handler betreten wird.

+0

Ich habe die Frage in einer Weise erweitert, die ich noch denke, funktioniert, aber können Sie bitte bestätigen, dass ein zweiter Wurf auch funktionieren wird. – WilliamKF

+1

@William: Sobald Sie ein Semikolon nach "throw" setzen. :) [Diese Frage] (http://stackoverflow.com/questions/2474429/does-throw-inside-a-catch-ellipsis-rethrow-the-original-error/24474436#2474436) könnte von Interesse sein. – GManNickG

+0

Hoppla, Semikolon jetzt hinzugefügt. – WilliamKF

6

Ihr ursprünglicher Code war in Ordnung. Sie haben verschiedene Ausnahmearten abgefangen und eine Funktion aufgerufen, die eine Nachricht protokolliert und erneut gestartet hat. Die Anweisung throw muss nicht direkt im entsprechenden Block catch erscheinen. Wenn Sie eine dieser "Notiz" -Funktionen aufrufen und Sie sind nicht derzeit eine Ausnahme behandeln, dann wird Ihr Programm terminate() aufrufen.

Ihr neuer Code ist auch in Ordnung. Es ist in Ordnung, alles abzufangen und dann eine andere Funktion aufzurufen, die erneut durchläuft, um zu einem spezifischeren Handler zu gelangen. Das ist the exception dispatcher idiom described in the C++ FAQ. Es sieht etwas eigenartig aus, um die Ausnahme erneut auszulösen nach der Dispatching-Block ist fertig, aber wenn das gleiche throw Anweisung aufgetreten wäre nach noteError zurückgegeben (im ursprünglichen catch Block) statt wo es jetzt ist, dann wäre es völlig normal; Dies wird in der Norm §15.1/6 gezeigt.

+0

+1 für die 'beenden' Perspektive – Chubsdad

Verwandte Themen