Warum ist die Reihenfolge in dieser Funktion falsch?

... komplette Frage anzeigen

4 Antworten

Dabei hilft dir diese Seite:

http://www.cplusplus.com/reference/exception/exception/

Demnach ist die Reihenfolge also:

try { /* ... */ }
catch (something) { /* 8 */ }
catch (My_Exception) { /* 1 */ }
catch (out_of_range) { /* 6 */ }
catch (logic_error) { /* 3 */ }
catch (ios::failure) { /* 7 */ }
catch (exception) { /* 2 */ }
catch (string) { /* 4 */ }
catch (...) { /* 5 */ }

Dir muss aber klar sein, dass es mehrere mögliche richtige Lösungen gibt (sogar eine ganze Menge), und die exakte Reihenfolge ist (falls überhaupt) von den Projekt-Richtlinien oder z. B. dem Bauchgefühl deines Lehrers vorgegeben. :)

Im Anhang dieser Antwort findest du noch mal den C++ Exception Tree als Grafik. :)

Den Exceptions sieht man die Vererbungshierarchie leider nicht an, aber völlig unbekannte (something) sollten oben stehen, und die Ellipse (die drei Punkte) sollte ganz am Ende stehen.

Bei allem anderen musst du die Vererbungshierarchie beachten, und um auf Nummer Sicher zu gehen, sollten bekannte Nicht-Exception Typen (string) ebenfalls direkt vor der Ellipse stehen.

Für PODs gelten die selben Regeln, wie für Klassen, also beachte auch hier die Hierarchie.

Die Position von primitiven Datentypen ist eigentlich egal, da von denen nicht geerbt werden kann, aber hierbei solltes du zwischen signed und unsigned Werten unterscheiden!

Des weiteren wird zwischen const, Zeigern, Referenzen und deren Kombinationen ebenfalls unterschieden. Hier gelten die üblichen Regeln.

Da aber in deinem Beispiel weder PODs, noch Zeiger oder ähnliches auftauchen, ist das vermutlich nicht relevant für dich, und du kannst die letzten paar Absätze meiner Antwort ignorieren. :)

Viel Spaß! :)

Antwort bewerten Vielen Dank für Deine Bewertung

Es gibt bei Catch-Blöcken im allgemeinen nicht "die" richtige Reihenfolge, sondern mehrere sinnvolle und mehrere sinnlose Reihenfolgen.

Wenn Klasse exceptionB von Klasse exceptionA erbt

class exceptionB: exceptionA {};

dann hat es keinen Sinn, erst exceptionA und danach exceptionB abzufangen, da ja jede exceptionB auch eine exceptionA ist und schon im vorigen Block abgefangen wird.

// sinnlose Reihenfolge:
catch (exceptionA) {/* code */} // hier werden auch exceptionB abgefangen
catch (exceptionB) {/* code */} // dieser Code wird nie ausgeführt
// sinnvolle Reihenfolge:
catch (exceptionB) {/* code */} // dieser Code wird bei einer exceptionB ausgeführt
catch (exceptionA) {/* code */} // dieser Code wird bei einer exceptionA ausgeführt, die keine exceptionB ist

du müsstest also untersuchen, welche der abgefangenen Klassen jeweils von welcher anderen erbt und die catch-Blöcke so sortieren, dass immer die weiter abgeleitete Klasse vor der weniger weit abgeleiteten steht.

Bei Klassen, von denen keine in der "Ahnentafel" der anderen steht, ist die Reihenfolge egal, die können sich ja nicht ins Gehege kommen.

(Statt Klassen sind auch Interfaces möglich oder allgemein alles, als was eine abgeleitete Klasse aufgefasst wird.)

Aber ohne die Stammbäume der Vererbungen und Implementierungen der abgefangenen Klassen könnte ich nicht sagen, was dort falsch ist.

Antwort bewerten Vielen Dank für Deine Bewertung

Dein zweiter catch ist der allgemeinste - der fängt jede Exception. Das bedeutet, egal, was geworfen wird, spätestens beim zweiten catch ist Schluss.

Beim Anordnen der catch-Blöcke fängt man bei der spezifischsten Exception an und arbeitet sich zur allgemeinsten hoch.

Stell dir eine Sortieranlage für Kleidung vor. Auf einem Fließband läuft Kleidung an fünf Arbeitern vorbei.

Arbeiter 1 soll alle roten T-Shirts aussortieren, Arbeiter 2 alle T-Shirts, Arbeiter 3 alle Baumwoll-Oberbekleidung, Arbeiter 4 alle Oberbekleidung und Arbeiter 5 alle Kleidungsstücke. Wenn du jetzt Arbeiter 5 an die zweite Position stellst, fängt der alles ab, was kein rotes T-Shirt ist. Ein blaues T-Shirt zum Beispiel ist zwar ein T-Shirt, aber eben zweifellos ein Kleidungsstück. Arbeiter 5 wird es also gemäß seines Auftrages aussortieren, bei Arbeiter 2 (der alle T-Shirts aussortieren soll) kommt es gar nicht mehr an.

Prinzip verstanden?

Antwort bewerten Vielen Dank für Deine Bewertung

Deinen Code kann man überhaupt nicht lesen.

mit try{} klammerst du Anweisungen, bei den beim Auftreten einer Schutzverletzung in den catch-Zweig gesprungen werden soll. Mit throw löst du eine Schutzverletzung willkürlich aus.

Antwort bewerten Vielen Dank für Deine Bewertung
Kommentar von JamesOffice
10.12.2015, 11:18

#include <exception> #include <String> #include <iostram> using namespace std; class My_Exception : public exception {}; class something {}; void func1() { throw exception(" no t h ing ")}void func2() { throw string(" 12345 "); } void func3() { throw out_of_range(" abcde "); }void func4() { throw ios::failure(" i o s "); }void func5() { throw My_Exception(); } void func6() { throw something(); } void func7() { throw logic_error(" t r u e "); } int main() { try { func1(); func2(); func3(); func4(); func5(); func6();func7(); } catch (My_Exception) {/*1*/ } catch (exception) {/*2*/ } catch (logic_error) {/*3*/ } catch (string) {/*4*/ } catch (...) {/*5*/ } catch (out_of_range) {/*6*/ } catch (ios::failure) {/*7*/ } catch (something) {/*8*/ } return 0; }
0

Was möchtest Du wissen?