2012-09-22 11 views
13

Heute Erneutes Auslösen fand ich einen Fehler in einem catch Block:Losing Art Ausnahme, wenn eine Ausnahme von einem catch-Block

catch (const exception& e){ 
    // do something 
    // throw e; <-- bug! 
    throw; // <-- right thing to do 
} 

Grundsätzlich, wenn ich die Ausnahme eausdrücklich erneut auslösen, bekomme ich ein neues std::exception rekonstruiert, in Tatsache die Nachricht von der what() Methode war die Standardeinstellung std::string, anstelle von meiner benutzerdefinierten Nachricht.

Was ist die Erklärung? Ich dachte, dass throw; nur eine Kurzschrift von throw ExceptionJustCaught; ist.

+0

Es ist der Unterschied zwischen einem Wert und einer Referenz. –

+0

Dies ist ein sehr wichtiges Konzept, das oft übersehen wird (und meiner Meinung nach eine knifflige Syntax, die zumindest eine Warnung sein sollte, wenn sie kompiliert wird ..). Gute Frage! – NHDaly

Antwort

13

Ausnahmeobjekte sind etwas Besonderes. Sie sind an einem besonderen Ort im Gedächtnis aufgebaut, und ihre Lebensdauer wird durch den Fangblock bestimmt, in dem sie gefangen sind.

Wenn Sie throw e; sagen, die Lebensdauer der ursprünglichen Ausnahme endet am Ende des catch-Blockes, und Sie werden durch das Kopieren e eine neue Ausnahme zu werfen, so dass ein klassisches Slicing Problem Herstellung: Da e eine polymorphe Referenz Bei einem Objekt, dessen dynamischer Typ in der Regel mehr abgeleitet ist als std::exception, schneiden Sie den abgeleiteten Teil des Objekts ab.

dagegen throw; ist eine spezielle Anweisung, die die ursprüngliche Ausnahme reaktiviert, so dass es nicht mehr aufgefangen, und ihre Lebensdauer tut nicht Ende am Ende des Blockes mehr. Wenn Sie eine nicht konstante Referenz erfassen, können Sie das Exception-Objekt weiterhin ändern und erneut eine Statusänderung durchführen, um die unteren Catch-Blöcke zu kommunizieren. Aber bedenken Sie, dass das Nachstreichen anders ist als das Werfen einer neuen Ausnahme!

8

Nur ein throw löst die aktuelle Ausnahme durch Verweis. throw e Kopieren erstellt eine neue Ausnahme zum Werfen. Dies ist ähnlich wie return funktioniert.

+0

"durch Bezugnahme". Genau, das sollte nicht die richtige Umsetzung von 'was()' verlieren, die meine Botschaft trägt. –

+0

Können Sie ein vollständiges, kompilierbares Codebeispiel mit so wenig Zeilen wie möglich bereitstellen, das das Problem veranschaulicht? Höchstwahrscheinlich behält der Kopierkonstruktor die Nachricht nicht bei. –

+0

Kerreks Antworten sehen korrekt aus, ich vermutete, dass es ein Problem mit dem Schneiden gibt, deshalb werde ich die Frage nicht bearbeiten, da ich denke, dass sie richtig beantwortet wurde. Vielleicht hat David mit genau anderen Worten recht, aber ehrlich gesagt ist es nicht klar genug. –

Verwandte Themen