2009-10-31 6 views
32

Was ist der Gültigkeitsbereich des Ausnahmeobjekts in C++? Wird der Catch-Handler ausgeführt? Wenn ich ein unbenanntes Exception-Objekt erzeuge und es ausschreibe, spielt es beim Abfangen dieser Exception keine Rolle, ob ich es durch eine const-Referenz oder eine nicht-konstante Referenz abfange.Bereich des Ausnahmeobjekts in C++

+3

Fragen Sie nach der * Lebenszeit *? – Joren

+0

Ja ... wann wird es zerstört werden? – Naveen

+8

Um Jorens Frage zu klären: Der Begriff _scope_ bezieht sich normalerweise auf die Region (Codezeilen), in der die Variable einen Namen hat.Das Wort _scope_ wird oft missbraucht, um _lifetime_ zu bedeuten, was, wie Sie verstanden haben, wie lange die Variable tatsächlich im Speicher liegt. – Thomas

Antwort

32

Wenn ein throw Ausdruck ausgewertet wird, wird ein Ausnahmeobjekt aus dem Wert des Ausdrucks initialisiert. Das Exception-Objekt, das ausgelöst wird, erhält seinen Typ vom statischen Typ des throw-Ausdrucks und ignoriert alle Qualifizierer const und volatile. Für Klassenarten bedeutet dies, dass Kopierinitialisierung durchgeführt wird.

Der Geltungsbereich des Ausnahmeobjekts liegt außerhalb des Bereichs des Blocks, in dem der Throw auftritt. Stellen Sie sich vor, Sie leben in einem speziellen Ausnahmebereich auf einer Seite des normalen Callstacks, in dem lokale Objekte leben.

In einem catch Block wird der Name, der mit dem gefangenen Ausnahmeobjekt initialisiert wurde, mit diesem Ausnahmeobjekt und nicht mit dem Argument throw initialisiert, auch wenn es sich um einen Lvalue handelte.

Wenn Sie catch über nicht-const Referenz, dann können Sie das Ausnahmeobjekt mutieren, aber nicht, was es initialisiert wurde. Sie können das Verhalten des Programms ändern, wenn Sie die Ausnahme auf eine Weise neu werfen, die nicht möglich war, wenn Sie von Wert oder const-Referenz abgefangen wurden (const_cast s beiseite).

Das Ausnahmeobjekt wird zerstört, wenn der letzte Catch-Block, der nicht durch einen erneuten Wurf (d. H. Eine parameterlose Auswertungsauswertung) beendet wird.

4

Zunächst geht das Objekt, das Sie werfen, fast sofort außer Reichweite. Was von Exception-Handlern abgefangen wird, ist eine Kopie des ursprünglichen Objekts. Diese Kopie wird gelöscht, nachdem der Catch-Handler ausgeführt wurde es sei denn, Sie fangen es nach Wert (nicht per Referenz). In diesem Fall wird eine weitere Kopie erstellt. Aber Sie sollten es auf jeden Fall als Referenz (vorzugsweise const one) fangen.

+0

Wie wäre es mit einem Zeiger auf etwas wie MFC? Sie müssen andere Objekte als Objekte des Klassentyps berücksichtigen, die in der Frage und Ihrer Antwort impliziert sind. – Sam

+0

Zeiger werden auch kopiert, aber niemand kümmert sich normalerweise :) – vava

8

Das Ausnahmeobjekt ist nur im Block catch verfügbar. Sie können das Ausnahmeobjekt nicht außerhalb des Blocks catch verwenden. Folgende Schritte passieren, wenn Sie eine Ausnahme und fangen werfen:

try 
{ 
MyException anObject; 
throw anObject; //1 

} 
catch(MyException exObject) 
{ 
} 
  • Die throw Klausel (// 1) empfängt das lokale Objekt anObject, und behandelt sie als Wert Argument: es eine Kopie des anObject schafft.
  • Der Handler catch fängt ein MyException-Objekt ab, das wiederum ein Wertparameter ist. In diesem Moment wird eine weitere Kopie erstellt.
  • Wenn der Handler catch implementiert hätte, um eine Referenz auf ein Objekt (catch (MyException &o)) zu erhalten, wird die zweite Kopie vermieden.
  • Wenn catch Handler das Ausnahmeobjekt von const& empfängt, können Sie nur const Methoden aufrufen.
Verwandte Themen