šHgeocities.com/Vienna/Stage/4793/excp3.htmgeocities.com/Vienna/Stage/4793/excp3.htmdelayedx׸ÕJ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Č0¤£#OKtext/html€Cmo#˙˙˙˙b‰.HMon, 18 Dec 2000 15:41:52 GMTćMozilla/4.5 (compatible; HTTrack 3.0x; Windows 98)en, *׸ÕJ# Das Fangen

Zurück ] Nach oben ] Weiter ]

 

Das Fangen&Werfen-Spiel

Wie wir schon gesehen haben, geschieht das Fangen von Exception über das Schlüsselwort catch, welches einen Handler einleitet. Doch wie genau identifiziert der Compiler den passenden Handler?

Betrachten wir folgendes

try {
    throw E();  
}
catch (H) { 
    ... // Wann kommen wir hierhin?
}

Der Handler wird dann aufgerufen, wenn

  1. H vom selben Typ wie E ist

  2. H eine eindeutige öffentliche Basisklasse von E ist

  3. H und E Zeigertypen sind und 1. und 2. für die Typen gilt auf die sie zeigen

  4. H eine Referenz ist und 1. und 2. für den Typ gelten, auf den H verweist.

Weiterwerfen

Nachdem ein Handler eine Ausnahme verarbeitet hat, kann er evtl. entscheiden, daß in seinem Kontext diese Ausnahme nicht vollständig bearbeitet werden kann. Deswegen gibt es die Möglichkeit, die selbe Ausnahme (wirklich die selbe, auch wenn sie auf eine Basisklasse zurechtgesliced wurde!), weiterzuwerfen. Dies geschieht durch die Anweisung throw() ohne Parameter. Gibt es keinen weiteren Handler für diese Klasse, wird von Compiler terminate() aufgerufen.

Alleskönner und die Reihenfolge von Handlern

Wie bei Funktionen bedeuten die Punkte ... "jedes Argument", daher bedeutet catch(...) "fange jede Exception". Man könnte diese Möglichkeit z.B. als Aufräumaktion in einem Fehlerfall nutzen und die Exception weiterwerfen.

Wie wir gesehen haben, kann eine abgeleitete Ausnahme von Handlern mehrerer Ausnahmetypen gefangen wer­den. Deswegen ist die Reihenfolge wichtig, in der die Handler im try-Block stehen, denn in dieser werden sie auch ausgeführt.

Nehmen wir unseren Int_overflow noch einmal ....

void f()  
{ 
    try { 
        //....
    }
    catch (...) {
        // fängt auf jeden Fall Int_overflow
    } 
    catch ( Matherr& m ) { 
        ... 
    } 
    catch ( Int_overflow* p ) { 
        ...
    }
}

Dieses Negativbeispiel zeigt, wie man es nicht machen sollte. Der speziell auch Int_overflow zugeschnittene Handler wird nie aufgerufen. Auch wenn man den "Fange alles"-Handler entfernte, würde er immer noch nicht berücksichtigt werden, da Int_overflow von Matherr abgeleitet ist.