Syntax der Standard-Exception-Behandlung in C++

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Standard-Exception-Behandlung in C++


Für die Exception-Behandlung sind die folgenden drei Schlüsselwörter erforderlich: try, throw und catch. Mit dem Schlüsselwort throw wird eine Exception erzeugt. Der try-Block enthält Anweisungen, die Exceptions auslösen können. Danach folgen eine oder mehrere catch-Anweisungen. Jede catch-Anweisung behandelt einen bestimmten Exception-Typ.

Hinweis: Die Schlüsselwörter try, catch und throw sind in C-Programmen nicht zulässig.

Der try-Block

Der try-Block enthält eine oder mehrere Anweisungen, die eine Exception auslösen können. Ein Programm löst durch Ausführen einer throw-Anweisung eine Exception aus. Die throw-Anweisung tritt im Allgemeinen in einer Funktion auf. Zum Beispiel:

 void SetFieldValue(DF *dataField, int userValue)
 {
     if ((userValue < 0) || userValue > 10)
         throw EIntegerRange(0, 10, userValue);
     // ...
 }

Ein anderer Programmteil kann das ausgelöste Exception-Objekt abfangen und es entsprechend behandeln. Zum Beispiel:

 try {
 	SetFieldValue(dataField, userValue);
 }
 catch (EIntegerRange &rangeErr) {
 	printf("Expected value between %d and %d, but got %d\n", rangeErr.min,
 		rangeErr.max, rangeErr.value);
 }

Wenn in diesem Beispiel die Funktion SetFieldValue feststellt, dass ihre Eingabeparameter ungültig sind, kann sie eine Exception auslösen, um dies anzuzeigen. Wird eine Exception ausgelöst, dann wird die Anweisung printf ausgeführt. Wird keine Exception ausgelöst, dann wird die Anweisung printf nicht ausgeführt.

Nach einem durch das Schlüsselwort try gekennzeichneten try-Block muss unmittelbar die Behandlungsroutine (angegeben durch das Schlüsselwort catch) folgen. Der try-Block ist eine Anweisung, die die Ablaufsteuerung bei der Programmausführung festlegt. Wird in dem try-Block eine Exception ausgelöst, wird die Programmsteuerung an die geeignete Exception-Behandlungsroutine übergeben.

Die Behandlungsroutine ist ein Codeblock zur Behandlung der Exception. In der Sprache C++ muss unmittelbar nach einem try-Block mindestens eine Behandlungsroutine angegeben werden. Das Programm sollte eine Behandlungsroutine für jede Exception enthalten, die das Programm erzeugen kann.

Die throw-Anweisung

Die throw-Anweisung kann verschiedene Objekttypen auslösen. Objekte in C++ können im Allgemeinen per Wert, Referenz oder Zeiger ausgelöst werden. Zum Beispiel:

 // throw an object to be caught by value or reference
 throw EIntegerRange(0, 10, userValue);
 
 // throw an object to be caught by pointer
 throw new EIntegerRange(0, 10, userValue);

Hinweis: Um Speicherlecks zu vermeiden, sollten Sie Exceptions per Wert auslösen und per Referenz abfangen. Wenn Sie eine Exception per Zeiger abfangen, kann es sein, dass Sie das Exception-Objekt nicht löschen können.

Hinweis: Um eine Exception per Wert auszulösen, muss sie einen public-Kopierkonstruktor und einen public-Destruktor haben.

Darüber hinaus kann die throw-Anweisung primitive Typen, wie Integer- oder Zeigertypen, auslösen. In den beiden folgenden Beispielen werden Features gezeigt, die hauptsächlich wegen der Vollständigkeit mit dem Standard vorhanden sind. Es sollten aber besser Exceptions mit einem mehr beschreibenden Charakter ausgelöst werden. Es gibt Sonderfälle für das Auslösen von integrierten Typen, wie Integertypen. Zudem sollten Exceptions nicht per Zeiger ausgelöst werden.

 // throw an integer
 throw 1;
 
 // throw a char *
 throw "foo";

Exception-Objekte können effizienter als primitive Werte sein, weil:

  • Die Exception eine bessere Beschreibung haben kann.
  • Die Exception mithilfe des Klassenpolymorphismus gefiltert werden kann.

In den meisten Fällen sollten Sie Exceptions per Referenz und insbesondere per const-Referenz abfangen. In manchen Fällen müssen Sie beim Abfangen von Objekten per Wert sehr sorgfältig vorgehen. Per Wert abgefangene Objekte müssen vor ihrer Zuweisung zum catch-Parameter kopiert werden. Wenn ein Benutzer einen Kopierkonstruktor bereitstellt, wird dieser aufgerufen, was aber ineffizient sein kann.

Die catch-Anweisung

Die catch-Anweisung hat mehrere Formen. Objekte können per Wert, per Referenz oder per Zeiger abgefangen werden. Außerdem können für den catch-Parameter const-Modifizier angewendet werden. Einem einzelnen try-Block können mehrere catch-Anweisungen zugeordnet werden, damit ein Block mehrere verschiedene Exception-Typen abfangen kann, und es sollte für jede mögliche Exception eine catch-Anweisung vorhanden sein. Zum Beispiel:

 try
     CommitChange(dataBase, recordMods);
 catch (const EIntegerRange &rangeErr)
     printf("Got an integer range exception");
 catch (const EFileError &fileErr)
     printf("Got a file I/O error");

Wenn die Funktion CommitChange mehrere Subsysteme verwendet, und diese Subsysteme verschiedene Exception-Typen auslösen können, sollten Sie jeden Exception-Typ separat behandeln. Wenn Sie mehrere catch-Anweisungen für eine try-Anweisung angeben, können Sie für jeden Exception-Typ Behandlungsroutinen vorsehen.

Wenn ein Exception-Objekt von einer Basisklasse abgeleitet ist, können Sie spezielle Behandlungsroutinen für einige abgeleitete Exceptions hinzufügen, aber auch eine allgemeine Behandlungsroutine für die Basisklasse vorsehen. Hierzu ordnen Sie die catch-Anweisungen in der Reihenfolge an, in der sie durchsucht werden sollen, wenn eine Exception ausgelöst wird. In dem folgenden Code wird beispielsweise zuerst EIntegerRange und dann ERange behandelt, von dem EIntegerRange abgeleitet ist.

 try
     SetFieldValue(dataField, userValue);
 catch (const EIntegerRange &rangeErr)
     printf("Got an integer range exception");
 catch (const ERange &rangeErr)
     printf("Got a range exception");

Schließlich können Sie mit der Sonderform catch(...) festlegen, dass die Behandlungsroutine alle Exceptions abfängt, die nach dem try-Block ausgelöst werden. Diese Anweisung teilt dem Exception-Behandlungssystem mit, dass die Behandlungsroutine für alle Exceptions aufgerufen werden soll. Zum Beispiel:

 try
     SetFieldValue(dataField, userValue);
 catch (...)
     printf("Got an exception of some kind");

Siehe auch