Am 14. September 2017 haben wir eine überarbeitete Fassung unserer Datenschutzrichtlinie veröffentlicht. Wenn Sie video2brain.com weiterhin nutzen, erklären Sie sich mit diesem überarbeiteten Dokument einverstanden. Bitte lesen Sie es deshalb sorgfältig durch.

C++ Grundkurs

Catch-Block

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Die Behandlung einer Ausnahme erfolgt in einer C++-Anwendung innerhalb eines catch-Blocks. Dieses Video bietet grundlegende Informationen zu dieser Thematik.
06:20

Transkript

In dieser Lektion will ich Ihnen den catch-Block vorstellen. Der catch-Block als Handler, der sich der Ausnahme annimmt. Auf einen try-Block können mehrere catch-Blöcke folgen. Die catch-Blöcke werden in der Reihenfolge, in der sie im Sourcecode stehen, abgearbeitet und der erste catch-Block, der passt, wird ausgeführt. Es gibt einen besonderen catch-Block. Das ist die sogenannte Ellipse. Die sehen Sie hier. Das ist sozusagen ein catch all catch-Block. Der kann jede Ausnahme annehmen. Aus dieser Umschreibung, die ich Ihnen hier oben gegeben habe, folgt eine einfache Regel für catch-Blöcke. Sie sollten vom Speziellen zum Allgemeinen geordnet sein. Das heißt, sie sollten eine Ausnahme so speziell wie möglich fangen. Noch ein weiterer interessanter Punkt. Eine Exception sollten Sie in einem catch-Block, sprich in der Signatur des catch-Blocks, als konstante Referenz annehmen, um polymorphes Verhalten zu unterstützen. Was heißt das? Wenn Sie ein polymorphes Objekt haben, sprich ein Objekt, dessen Typ erst zur Laufzeit bestimmt wird, müssen Sie natürlich sichergehen, dass Ihr catch-Block dieses Verhalten respektiert. Jetzt will ich Ihnen drei catch-Blöcke in der Anwendung zeigen. Hier habe ich ein Programm. Ich fange bei main an und dann arbeite ich mich mit Ihnen durch das Programm durch. Hier habe ich eine funcWithException, wirft eine Exception und dann habe ich hier drei catch-Blöcke, die die Exception fangen sollte. Der erste catch-Block fängt Exceptions vom Typ bad_alloc. bad_alloc sind Exceptions, die dann ausgelöst werden, wenn ich mir Speicher besorgen will und ich bekomme den Speicher nicht mehr. Dann hier eine vom Typ std::exception und hier der catch-all-Block. Jetzt schaue ich mir mit Ihnen die Funktion funcWithException an. Die ist hier. In dieser Funktion verwende ich einen Vektor von int. Den initialisiere ich mit 5 Werten. Was mache ich im try-Block? Ich schreibe auf die sechste Stelle einen Wert und das kann nicht gut gehen. Die Funktion oder Methode at des Vektors myVec passt aber auf und sie passt auf in dem Sinne, dass sie mitbekommt, wenn ich über die Grenzen hinausschreibe. Aus diesem Grund wirft sie eine Ausnahme und hier gehe ich mit der Ausnahme um. In der ersten Zeile, das sehen Sie hier, zeige ich die Fehlermeldung der Exception an, e.what. In der zweiten Zeile verwende ich zweimal ein Makro. Hier verwende ich das Makro Line. Dadurch bekomme ich heraus, in welcher Zeile ich bin. Hier verwende ich das Makro __File__, damit bekomme ich raus, in welcher Datei ich bin. Wenn Sie sich die Fehlermeldung anschauen, dann ist die eigentlich schon relativ aussagekräftig. Der Vektor sagt _M_range_check. Das ist wohl die Art der Exception. Drückt wohl aus, dass ich irgendwas im Range des Sektors verbrochen habe. Das war in der Line 15. Schaut gut aus. Das File hieße src/exception.cpp. Das ist schon sehr aussagekräftig. Was ich aber jetzt tue, ist die Exception weiterzuschmeißen, weil ich sage, ich kann diese Exception an dieser Stelle nicht behandeln, also gebe ich ein wenig Information aus und schmeiße sie weiter. Auf einen Punkt will ich hier noch explizit hinweisen. Ich verwende hier nicht std::cout, sondern den Ausgabekanal std::cerr. Der Kanal ist auch mit der Konsole verbunden. Sie sehen das auch hier. Aber der feine Unterschied zwischen std::cout und stc::cerr ist, std::cout ist gepuffert. Das heißt, wenn Sie etwas auf std::cout schreiben, so wie ich es hier tue, std::cout << “test“, ist das Problem, dass diese Ausgabe nicht sofort in der Konsole landet, sondern erst gepuffert wird und das heißt insbesondere, wenn eine Exception auftritt, dass das System gar nicht mehr die Zeit hat, diese Ausgabe rauszuschreiben. Sie sehen das also gar nicht. std::cerr ist dagegen ungepuffert. Das wird also direkt auf die Konsole geschrieben. Das heißt, Sie sehen in Ihrer Fehlermeldung, in Ihrer Ausgabe, genau das, was gerade aktuell passiert. Jetzt habe ich die Ausnahme wieder weitergeschmissen und Sie sehen, die Ausnahme ist vom Typ std::exception, da ich eine std::exception verwendet habe. Ich bekomme die endgültige Meldung std::exception. Genau die hier. Da ich hier die Exception ausreichend behandelt habe, läuft mein Programm wohldefiniert weiter. Wohldefiniert ist ein guter Punkt. Es läuft solange weiter, bis ich eine neue Exception werfe. Hier erkläre ich ein Exception-Objekt, myExcept vom Typ MyException und das habe ich ganz einfach hier so definiert. Da leite ich von der Standardklasse std::exception öffentlich ab, public und überschreibe in diesem Fall die what-Methode, weil ich einfach eine besondere Fehlermeldung ausschreiben will. In diesem Fall gibt die nur den Text MyException raus. Hier folge ich der Signatur, so wie es der Standard vorschreibt. Insbesondere verwende ich hier das Schlüsselwort noexcept. Das ist ein besonderes Schlüsselwort. noexcept drückt aus, dass eine Funktion keine Ausnahme werfen darf. Noch einmal, ich erzeuge hier mein Exception-Objekt, schmeiße es hier explizit, löse eine Exception aus, lande genau hier in dem Exception-Handler, dem catch-Block hier, da die Exception genau mit diesem Handler zusammenpasst. Gebe die Fehlermeldung aus, MyException, mache einen Zeilenumbruch und dann schmeiße ich die Exception noch einmal. Jetzt habe ich ein Problem, weil ich bin in main. Jetzt gibt es keine Routine mehr, die mein Exception fangen kann. Was nun passiert ist, dass std::terminate aufgerufen wird. std::terminate ruft dann abort auf und das war es. Mein Programm stürzt ab. Genau das sehen Sie hier. terminate, what(): MyException wird noch einmal ausgegeben und abgebrochen. In dieser Lektion habe ich Ihnen den catch-Block vorgestellt und Ihnen insbesondere den Tipp gegeben, dass Sie catch-Blöcke immer vom Speziellen zum Allgemeinen sortieren sollten, da die catch-Blöcke in der Reihenfolge, in der sie im Sourcecode verwendet werden ausgeführt werden. Was noch weiter interessant rund um catch-Blöcke ist, es gibt den catch-all-catch-Block. Das heißt, durch diese Ellipse, diese drei Punkte, wird es zu einem catch-Block, der jede Exception auffangen kann. Der soll natürlich an letzter Position kommen. Zum Schluss habe ich Ihnen noch das Zusammenspiel zwischen try, catch und throw an einem Beispiel gezeigt.

C++ Grundkurs

Steigen Sie in die mächtige Programmiersprache C++ ein und lernen Sie dabei alle wichtigen Funktionen mit Anwendungsbeispielen kennen.

8 Std. 14 min (147 Videos)
Derzeit sind keine Feedbacks vorhanden...
 

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!