Eine Exception (= Ausnahme) ist ein Objekt, das "geworfen" wird. Dieses Objekt hat, wie schon erwähnt einen Typ. Das kann ein std::exception sein, dein ProgramException, oder aber auch ein ganz normales "int", oder ein selbstdefinierter typ!
Wohin wird eine Exception geworfen? Die Exception "fliegt" solange, bis sie ein "catch"-Block auffängt, dabei fliegt sie auch den Funktionsaufruf-stack hoch.
Gibt es keinen "catch"-Block, ist die Exception unbehandelt (das wäre also dein Fehler!)
Das einfachste Beispiel ist folgendes:
Code: Alles auswählen
int main(int argc, char* argv[])
{
throw 123;
return 0;
}
Hier wird eine Exception vom typ "int" geworfen, und von niemandem Aufgefangen, also beendet sich das Programm mit "unhandled exception".
Du kannst es auch auffangen
Code: Alles auswählen
#include <iostream>
int main(int argc, char* argv[])
{
bool alles_in_ordnung = false;
try {
if (!alles_in_ordnung)
throw 123;
}
catch(int exc)
{
std::cerr<<"Ohje... Ein Fehler mit der Nummer "<<exc<<" ist aufgetreten. :-(\n";
}
return 0;
}
Wenn nicht alles_in_ordnung ist, wird die Exception geworfen und gleich wieder aufgefangen.
Bis jetzt war das alles nicht so nützlich. Jetzt kommt aber der echte Vorteil von Exceptions: du musst eine exception nicht in der gleichen Funktion auffangen, in der sie geworfen wurde! Du kannst sie auch in einer unterfunktion werfen, und ganz oben abfangen.
Code: Alles auswählen
#include <iostream>
class MeineBibliothekException {
};
void machwas()
{
bool alles_in_ordnung = false;
if (!alles_in_ordnung)
throw MeineBibliothekException();
}
void meine_bibliothek()
{
machwas();
}
int main()
{
try {
meine_bibliothek();
}
catch(const MeineBibliothekException&)
{
std::cerr<<"Ein Fehler ist aufgetreten.\n";
}
return 0;
}
Aufpassen musst du nur auf folgendes: wenn die Exception geworfen wird, wird das Programm quasi "Abgebrochen", und springt zum catch-Block. Natürlich wird auch der Code danach nicht mehr ausgeführt, es besteht die Gefahr von Speicherlecks oder nicht geschlossenen Dateien.
Das klingt jetzt schlimmer als es ist, denn in C++ packt man üblicherweise alle "sensiblen" ressourcen in eine Klasse, dessen Destruktor z.B. speicher löscht oder Dateien schließt. Dieses Prinzip nennt man
RAII.
Wenn nämlich deine Exception durch die Gegend fliegt, werden alle Destruktoren der lokalen Variablen jedes Frames aufgerufen.
Haters gonna hate, potatoes gonna potate.