1 / 32

Gliederung

Gliederung. Ausnahmebehandlung Grundphänomene Am Beispiel Konto: 3 Varianten Möglichkeiten bei der Verwendung von Klassenobjekten 4 Varianten. Beispiel: Kontoführung. Ich kann ein Konto eröffnen, auf ein Konto einzahlen, von einem Konto abheben, ein Konto überziehen,

jerome-paul
Download Presentation

Gliederung

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Gliederung • Ausnahmebehandlung • Grundphänomene • Am Beispiel Konto: 3 Varianten • Möglichkeiten bei der Verwendung von Klassenobjekten • 4 Varianten

  2. Beispiel: Kontoführung • Ich kann • ein Konto eröffnen, • auf ein Konto einzahlen, • von einem Konto abheben, • ein Konto überziehen, • ein Konto wieder schließen. • (Abstrakter Datentyp)

  3. Klasse EinfachesKonto class Konto { protected: int stand; public: Konto(){stand = 0;} ~Konto(){ cout << "Nachricht" << endl; } void Einzahlen(int k) {stand += k;} int Abheben(int k) { stand -= k; return k; } int KontoStand() {return stand;} };

  4. Klasse EinfachesKonto (Forts.) int main() { int i, j, st; Konto * kto = new Konto; for (i = 0; i < 5; i++) { j = rand(); cout << "\nEingezahlt: \t" << j; kto ->Einzahlen(j); cout << ",\tAbgehoben:\t" << kto ->Abheben((i+1)*rand()); st = kto ->KontoStand(); cout << ",\tKontostand:\t" << st << (st < 0? " *": ""); } kto ->~Konto(); } Konto1

  5. Klasse EinfachesKonto (Forts.) Eingezahlt: 16838, Abgehoben: 5758, Kontostand: 11080 Eingezahlt: 10113, Abgehoben: 35030, Kontostand: -13837 * Eingezahlt: 31051, Abgehoben: 16881, Kontostand: 333 Eingezahlt: 23010, Abgehoben: 29676, Kontostand: -6333 * Eingezahlt: 16212, Abgehoben: 20430, Kontostand: -10551 * Konto bei Geschaeftsschluss aufgeloest

  6. Überziehung des Kontos • Wie wird das behandelt? • Annahme: • Die Überziehung hat Konsequenzen: • Konto wird dann aufgelöst. • Möglichkeiten: • nach jeder Abhebung wird gefragt, ob das Konto überzogen ist, • ja: Konto auflösen, Abbruch • nein: weitermachen wie gewohnt.

  7. Überziehung des Kontos • ist für den Code umständlich: • Der Normalfall und der Ausnahmefall werden ineinander vermischt behandelt • Alternative: Ausnahmebehandlung • Wenn die Ausnahmesituation entsteht, wird dem benutzen-den Programmteil gesagt: • „Hier stimmt etwas nicht, es muß etwas geschehen“ • d.h. Ausnahmebehandlung

  8. Modifikation der Klasse class Konto { protected: int stand; public: Konto(){stand = 0;} ~Konto(){cout << "Nachricht";} void Einzahlen(int k) {stand += k;} int Abheben(int k) {stand -= k; if (stand < 0) throw k; return k; } int KontoStand() {return stand;} };

  9. Interpretation • Wenn diese Bedingung stand < 0 erfüllt ist, aktiviere eine Ausnahme mit dem Wert k: (das ist der Betrag, bei dessen Abheben das Konto überzogen wurde) • Die Ausnahme muß irgendwo behandelt werden: (d.h. zum throw gehört ein catch)

  10. ... der Fänger Konto * kto = new Konto; try{ for (i = 0; i < 5; i++) { cout << "\nEingezahlt: \t" << ...; kto->Einzahlen(...); abh = kto->Abheben(...); cout << ",\nabgehoben: \t" << abh; st = kto->KontoStand(); cout << ",\tKontostand:\t" << st << (st < 0? " *": ""); } } catch(int t) { cout << "\nKonto ueberzogen .." << t << "DM\n"; kto->~Konto(); } Konto * kto = new Konto; for (i = 0; i < 5; i++) { cout << "\nEingezahlt: \t" << ...; kto->Einzahlen(...); abh = kto->Abheben(...); cout << ",\nabgehoben: \t" << abh; st = kto->KontoStand(); cout << ",\tKontostand:\t" << st << (st < 0? " *": ""); } Programm

  11. Ausgabe Eingezahlt: 16838, abgehoben: 5758, Kontostand: 11080 Eingezahlt: 10113 Konto ueberzogen beim Abheben von 35030 DM Konto aufgeloest Hier wurde die Ausnahme offenbar ausgelöst

  12. Anmerkungen • Der Aufruf einer Methode, die eine Ausnahme auslöst, muß in einem Block stattfinden, der mit try eingeleitet wird, also: try { ... Methode oder Funktion, die eine Ausnahme auslöst ... }

  13. Anmerkungen • Unmittelbar auf try folgt ein oder folgen mehrere catch zur Behandlung der Ausnahme: • catch ist parametrisiert: Der formale Parameter wird beim Behandeln der Ausnahme durch einen aktuellen Parameter ersetzt, der von throw gesetzt wird. • Analogie: • Funktionsvereinbarung: Arbeit mit formalen Parametern • Funktionsaufruf: Substitution durch aktuelle Parameter

  14. Anmerkungen • Kontrollfluß bei der Aktivierung einer Ausnahme: • Aktivieren der Ausnahme mitthrow <WurfGeschoß> • Suchen der passenden catch-Klausel • Ausführen des entsprechenden Blocks (mit Wurf-Geschoß als aktuellem Parameter) • Danach Verlassen der catch-Klausel und Weiterar-beit mit dem Block, der unmittelbar auf die catch-Klauseln folgt • Insbesondere: Keine Rückkehr in den try-Block oder die aktivierende Prozedur

  15. Beispiel (Forts.) • Verdacht auf Steuerbetrug, wenn ein zu hoher Betrag eingezahlt wird. --> Aktivierung einer Ausnahme. • Jedoch Problem: Kann die Ausnahme nicht mit throw k aktivieren, da die beiden Situationen auf diese Art nicht voneinander getrennt werden können. • Es gilt aber: Es können Instanzen beliebiger Klassen geworfen werden.

  16. Beispiel (Forts.) • Definiere zwei Klassen • Ueberziehung • VerdachtSteuerbetrug • Wirf entsprechende Ausnahmen • Behandle die Ausnahmen nach den Typen der geworfenen Argumente, also: • Ueberziehung könnte anders behandelt werden als VerdachtSteuerbetrug • z. B.: bei Ueberziehung schließen wir das Konto

  17. Modifiziertes Konto class Ueberziehung { public: int wert; Ueberziehung(int j) { wert = j; } }; class VerdachtSteuerbetrug { public: int wert; VerdachtSteuerbetrug(int z) { wert = z; } }; eine ganz normale Klasse noch eine ganz normale Klasse

  18. Modifiziertes Konto (Forts.) void Einzahlen(int k) { stand += k; if (k > 30000) throw new VerdachtSteuerbetrug(k); } int Abheben(int k) { stand -= k; if (stand < 0) throw new Ueberziehung(k); return k; } hier werden die entsprechenden Instanzen geworfen

  19. Behandlung der Ausnahmen catch(Ueberziehung * t) { cout << "\nKonto ueberzogen beim Abheben von " << t->wert << " DM\n"; kto->~Konto(); } catch (VerdachtSteuerbetrug * r) { cout << "\nZu hohe Einzahlung. Steuerbetrug? " << r->wert << endl; } Konto3.cpp Programm

  20. Ausgaben • Zweite Einzahlung: 31340 • Eingezahlt: 17000, • Abgehoben: 16838, Kontostand: 162 • Eingezahlt: 31340 • Zu hohe Einzahlung. Steuerbetrug? 31340 • --> Hier sind alle Ausnahmen behandelt <-- • Zweite Einzahlung: 3134 • Eingezahlt: 17000, • Abgehoben: 16838, Kontostand: 162 • Eingezahlt: 3134 • Konto ueberzogen beim Abheben von 5758 DM • Konto aufgeloest • --> Hier sind alle Ausnahmen behandelt <-- • Zweite Einzahlung: 31340 • Eingezahlt: 17000, • Abgehoben: 16838, Kontostand: 162 • Eingezahlt: 31340 • Zu hohe Einzahlung. Steuerbetrug? 31340 • --> Hier sind alle Ausnahmen behandelt <--

  21. Passendes catch? • Identifikation der passenden Behandlung? • throw T wird von catch (Klasse W) gefangen, falls gilt: • T ist vom Typ W oder der Typ von T erbt von W • diese catch-Klausel ist die erste Klausel, auf die diese Bedingung paßt.

  22. Beispiel: Definitionen Instanzen dieser Klassen sollen geworfen werden class eins {}; class zwei: public eins {}; class drei { public: void wirfEins() { cout << "\nin wirfEins\n"; throw new eins; } void wirfZwei() { cout << "\nin wirfZwei\n"; throw new zwei; } }; hier wird geworfen

  23. Klasse zwei ist Spezialfall von Klasse eins Benutzung Ausnahme1 void main() { drei * d3 = new drei; try { d3->wirfZwei(); } catch(eins *) { cout << "\nschmeiße eins\n"; } catch(zwei *) { cout << "\nschmeiße zwei\n"; } }

  24. Benutzung Ausnahme1A void main() { drei * d3 = new drei; try { d3->wirfZwei(); } catch(zwei *) { cout << "\nschmeiße zwei\n"; } catch(eins *) { cout << "\nschmeiße eins\n"; } }

  25. Diskussion • Ausgabe: • Ausnahme1: • in wirfZwei • schmeiße eins • Denn: catch(eins *)fängt die Ausnahmethrow (new zwei) (Regel: erste Klausel, die paßt). • Ausnahme1A: • in wirfZwei • schmeiße zwei

  26. Weiterwerfen: class vier { public: drei * three; vier() { three = new drei; } void wirf() { try{ three->wirfEins(); } catch(eins *) { cout << "\n\tgefangen!\n"; throw new zwei; } } }; Ausnahme3 Programm

  27. Was passiert? • Ausgabe: • in wirfEins • gefangen! • schmeiße zwei • In der Klasse vier wird in der Methode wirf durch den Aufruf von three->wirfEins() eine Ausnahme vom Typ eins aktiviert. • Die Ausnahme wird in der Methode wirf behandelt, indem eine Ausnahme von Typ zwei aktiviert wird, die in main behandelt wird.

  28. Klasse vier: Wiederholung class vier { public: drei * three; vier() { three = new drei; } void wirf() { try{ three->wirfEins(); } catch(eins *) { cout << "\n\tgefangen!\n"; throw new zwei; } } };

  29. Klasse vier: exotisch (?) wirft Ausnahme vom Typ eins class vierExotisch { public: drei * three; vierExotisch () { three = new drei; } void wirf() { try{ three->wirfEins(); } catch(zwei *) { cout << "\n\tgefangen!\n"; throw new zwei; } } };

  30. Was passiert? • Die Ausnahme vom Typ eins wird nicht in der Methode wirf, sondern in main behandelt. • Klar: • Es ist kein passender Fänger in der Methode vorhanden.

  31. Für heute: • Ende

More Related