try-Block
Eine Ausnahme, die in einem try-Block ausgelöst wird, kann möglicherweise von einem zugehörigen Handler behandelt werden.
Inhalt |
[bearbeiten] Syntax
try compound-statement handler-seq |
(1) | ||||||||
try ctor-initializer (optional) compound-statement handler-seq |
(2) | ||||||||
| compound-statement | - | eine zusammengesetzte Anweisung |
| handler-seq | - | eine nicht-leere Sequenz von Handlern |
| ctor-initializer | - | Member-Initialisierungsliste (nur für Konstruktoren) |
[bearbeiten] Normaler try-Block
Ein normaler try-Block ist eine Anweisung.
Wenn aus seiner compound-statement eine Ausnahme ausgelöst wird, wird die Ausnahme mit den Handlern in seiner handler-seq abgeglichen.
void f() { throw 1; // NOT handled by the handler below try { throw 2; // handled by the associated handler } catch (...) { // handles the exception 2 } throw 3; // NOT handled by the handler above }
[bearbeiten] Funktions-try-Block
Ein Funktions-try-Block ist eine spezielle Art von Funktionsrumpf.
Wenn aus seiner compound-statement oder ctor-initializer (falls vorhanden) eine Ausnahme ausgelöst wird, wird die Ausnahme mit den Handlern in seiner handler-seq abgeglichen.
int f(bool cond) { if (cond) throw 1; return 0; } struct X { int mem; X() try : mem(f(true)) {} catch (...) { // handles the exception 1 } X(int) try { throw 2; } catch (...) { // handles the exception 2 } };
Ausnahmen, die in Destruktoren von Objekten mit statischer Speicherdauer oder in Konstruktoren von Objekten, die mit Nicht-Blockvariablen mit statischer Speicherdauer verbunden sind, ausgelöst werden, werden nicht von einem Funktions-try-Block in der main-Funktion abgefangen.
|
Ausnahmen, die in Destruktoren von Objekten mit Thread-Speicherdauer oder in Konstruktoren von Objekten, die mit Nicht-Blockvariablen mit Thread-Speicherdauer verbunden sind, ausgelöst werden, werden nicht von einem Funktions-try-Block in der Anfangsfunktion des Threads abgefangen. |
(seit C++11) |
Das Ende der compound-statement eines Handlers eines Funktions-try-Blocks zu verlassen, ist äquivalent zum Verlassen des Endes der compound-statement dieses Funktions-try-Blocks, es sei denn, die Funktion ist ein Konstruktor oder Destruktor (siehe unten).
[bearbeiten] Konstruktor- und Destruktor-try-Block
Für eine Klasse C gilt: Wenn der Funktionsrumpf ihrer Konstruktor- oder Destruktor-Definition ein Funktions-try-Block ist und während der Initialisierung oder Zerstörung von Cs Unterobjekten eine Ausnahme ausgelöst wird, wird die Ausnahme auch mit den Handlern in der handler-seq des Funktions-try-Blocks abgeglichen.
int f(bool cond = true) { if (cond) throw 1; return 0; } struct X { int mem = f(); ~X() { throw 2; } }; struct Y { X mem; Y() try {} catch (...) { // handles the exception 1 } ~Y() try {} catch (...) { // handles the exception 2 } };
Der Verweis auf ein nicht-statisches Mitglied oder eine Basisklasse eines Objekts im Handler eines Funktions-try-Blocks eines Konstruktors oder Destruktors für dieses Objekt führt zu undefiniertem Verhalten.
Wenn eine return-Anweisung in einem Handler des Funktions-try-Blocks eines Konstruktors erscheint, ist das Programm fehlerhaft.
Die aktuell behandelte Ausnahme wird erneut ausgelöst, wenn die Kontrolle das Ende eines Handlers des Funktions-try-Blocks eines Konstruktors oder Destruktors erreicht.
[bearbeiten] Kontrollfluss
Die compound-statement eines try-Blocks ist eine kontrollflussbeschränkte Anweisung.
void f() { goto label; // error try { goto label; // OK label: ; } catch (...) { goto label; // error } }
Eine Sprunganweisung (goto, break, return, continue) kann verwendet werden, um die Kontrolle aus einem try-Block (einschließlich seiner Handler) zu übertragen. Wenn dies geschieht, wird jede Variable, die im try-Block deklariert wurde, im Kontext zerstört, der ihre Deklaration direkt enthält.
try { T1 t1; try { T2 t2; goto label; // destroy t2 first, then t1 } catch(...) { // executed if an exception is thrown while destroying t2 } } catch(...) { // executed if an exception is thrown while destroying t1 } label: ;
[bearbeiten] Schlüsselwörter
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 98 | C++98 | eine switch-Anweisung kann Kontrolle übertragen in die compound-statement eines try-Blocks |
verboten |
| CWG 1167 | C++98 | es war nicht spezifiziert, ob ein Funktions-try-Block für einen Destruktor Ausnahmen von einem Basis- oder Mitgliedsdestruktor |
solche Ausnahmen abfängt |