Warnungen mit Exceptions?
-
Dann habe ich aber wieder diese vielen catch-Blöcke, und imho entspricht es mehr der OOP-Logik, dass ein Objekt seinen Zustand verwaltet und nicht jemand anderen die Botschaft schickt "Hilfe, mach was!"
Und auf Grund der Unübersichtlichkeit auf try/catch zu verzichten obwohl die Methode eine Exception werfen kann ist auch nicht das Gelbe vom Ei.
Wenn die Größe natürlich zur CompileTime feststeht dann brauch ich nur beim ersten Mal try/catch.
if(x!=800 && y !=600) throw; ... setres(800,600); // da brauch ich keinen try/catch mehr wenn ich weiß wann setres Exceptions wirft
Aber ansonsten ist es eine grobe Fahrlässigkeit.
Damit man diese Compiletime-Konstanten sofort auswerten kann gibts bereits ne Mailingliste dazu lang1@coollist.com , soll auf jeden Fall mit aufgenommen werden
[Das Plenken war Absicht...]
MfG SideWinder
-
godlikebot schrieb:
Shade of Mine schrieb:
Eben nicht.
Wieso sollte man soetwas schreiben?try { WasProbieren(); } catch(...) { Reagieren(); } try { WasAnderesProbieren(); } catch(...) { AuchDaraufReagieren(); } Und so weiter
Kann man denn sagen, dass C-Style Fehlerbehandlung in C++ schlechterer Stil ist als Exceptions?
Also mit Exceptions ist die Fehlerbehandlung IMHO erheblich einfacher (Mit entsprechenden Werkzeugen
RAII / ScopeGuard
). Normalerweise müsstest du eigentlich den Rückgabewert von praktisch jeder Funktion prüfen. Das ist a) lästig und b) ziemlich fehleranfällig, auch weil es in verschiedenen Bibliotheken jeweils anders gehandhabt wird (mal über Rückgabewert, mal errno, mal GetLastError). Da schreibe ich lieber meine Funktionen und werfe Exceptions. Der Aufrufer kann dann entscheiden, ob er es nochmal probieren will oder doch lieber den Vorgang abbricht und eine passende Fehlermeldung ausgibt.
void BenutzerHatButtonGeklickt() { try { WasProbieren(); WasAnderesProbieren(); } catch(const std::exception& e) { HatLeiderNichtGeklapptWeil(e.what()); } }
-
SideWinder schrieb:
Dann habe ich aber wieder diese vielen catch-Blöcke, und imho entspricht es mehr der OOP-Logik, dass ein Objekt seinen Zustand verwaltet und nicht jemand anderen die Botschaft schickt "Hilfe, mach was!"
Das Single-Responsibility-Principle steht dem entgegen. Ausserdem sind Exceptions sowieso für Fälle gedacht, in denen der Fehler nicht lokal behandelt werden kann. Das ist IMHO unabhängig von Stilfragen.
-
Aber du vergisst die Code-Übersichtlichkeit:
// Ein... if(!setres()) output_err(FATAL_ERROR,"Couldn't set resolution.",__FILE__,__LINE__); // ...ist sicherlich übersichtlicher als: try { setres(); } catch(error& obj) { output_err(FATAL_ERROR,obj.what(),__FILE__,__LINE__-4); }
Beinem vielleicht noch nicht, aber ab 10 untereinander wirds problematisch. Das obj.what() bringts halt noch zur detaillierteren Beschreibung des Fehlers (nun darf die Funktion ja dran - eine nicht gefundene Datei die zum Setzen der res benötigt wird, wird nicht plötzlich zu einem Grafikfehler...).
MfG SideWinder
-
Warum hat man sowas eigentlich nicht eingeführt:
// rückgabetyp name (params) : (exception_params) typ setres (int x, int y) : (const std::string&) { typ ret_data; // also rückgabewert benützen wir, keine status-meldung möglich if(x!=800 && x!=1024) warning("X is not a standard-value"); // string da std::string if(FAILED(Interface->SetScreenResolution(x,y))) error("can't set res"); // string da std::string return(ret_data); warning // Interne Reaktion { // Mach was bei Warnungen // Bevor das Schlüsselwort zählt impliziter aufruf von externer reaktion continue; // Weitermachen oben, andere Möglichkeit wäre throw } error { // Mach was bei Errors throw; // da fatal error } }
Zudem kann der Aufrufer noch folgendes machen:
void output_err (const std::string& bla) // da func ja std::string übernimmt { MessageBox(...); } void output_fatalerr (const std::string& bla) // dito { MessageBox(...); exit(-1); } func(1023,768) : warning(output_err), error(output_fatalerr);
Oder so etwas in diese Richtung. Gibts da Probleme damit? Ansonsten schlag ich das für lang1 vor.
MfG SideWinder
-
übersicht!
du springst ja wirr herum.
wie willst du auf ne warnung reagieren? entweder ist es ein fehler oder nicht. wenn es ein fehler ist, dann behandle oder wirf ihn. wenn es eine warnung ist, dann logge oder ignoriere sie.
da brauch ich kein 'catch'...
denn du hast im prinzip ein goto mit dynamischen labels gemacht.bzw: tut es hier eine funktion warning() vermutlich auch...
-
Ich weiß, dass ich da nur ein altes C-goto gekaspelt habe, aber ich finde den schlechten Stil nicht
Auf einen Fehler will ich schnell und an zentraler Stelle reagieren können um dann wieder mit meinem Code fortzufahren. Was ist daran so schlecht?
MfG SideWinder
-
tag schrieb:
Normalerweise müsstest du eigentlich den Rückgabewert von praktisch jeder Funktion prüfen. Das ist a) lästig und b) ziemlich fehleranfällig, auch weil es in verschiedenen Bibliotheken jeweils anders gehandhabt wird (mal über Rückgabewert, mal errno, mal GetLastError). Da schreibe ich lieber meine Funktionen und werfe Exceptions. Der Aufrufer kann dann entscheiden, ob er es nochmal probieren will oder doch lieber den Vorgang abbricht und eine passende Fehlermeldung ausgibt.
Wenn ich aber nen dicken try Block mit vielen Befehlen hab und daraus ne exception fange, dann weiss ich doch nicht, wo das Programm stecken geblieben ist.
Das ist ja das, was mich an exceptions etwas stört: Wenn eine exception geworfen wurde, dann ist das Programm (meistens) zum beenden verurteilt, oder seh ich das falsch? Der catch Block dient dann nur noch dazu, den Fehler zu loggen oder ne MessageBox auszugeben
Die Lösung wäre eben um jede Funktion einen try/catch Block zu legen, was aber Spaghetti-Code ergibt und eigentlich wenig anders ist als das überprüfen der Rückgabewerte der Funktionen.
-
Man muss nach der goldenen Mitte suchen
Beispiel:
void OnSaveButtonClicked() { try { ofstream(blabla); speichere_datei(); } catch(std::exception&) { MessageBox("Folgender Fehler ist beim Speichern aufgetreten: ..."); } }
Wenn du in diesem Fall das Programm einfach abbrichst, dann bin ich der erste, der dir in den Hintern tritt
Oder wenn du eine etwas kompliziertere Rechnung startest und dir auf einmal der Speicher ausgeht, warum dann nicht einfach das unvollständige Ergebnis verwerfen, den Ausgangszustand wiederherstellen und dem Benutzer sagen, was nicht geklappt hat? Oder wenn du eine Datei über's Netzwerk verschickst, warum sollte dein Programm abstürzen, wenn der Zielcomputer sich verabschiedet hat? In allen diesen Fällen ist ein normales Weiterarbeiten meistens problemlos möglich.
Wenn du aber z.B. nicht mal mehr genug Speicher hast, um ein Meldungsfenster anzuzeigen, dann lässt es sich nur noch schwer weitermachen...
Exceptions sind ja nur ein anderer Weg für Fehlerbehandlung. Wenn es mit klassischen Rückgabewerten keinen Grund gibt, das Programm zu beenden, dann gibt es den mit Exceptions auch nicht. Der (meines Erachtens) große Vorteil von Exceptions ist aber, dass einem die Fehlerbehandlung erleichtert wird. Es gibt eine einheitliche Fehlerbehandlung und ich kann mich eher damit auseinandersetzen, was im Fehlerfall zu tun ist, als den Fehlerfall überhaupt erstmal festzustellen.
-
gibts denn noch irgendwas, was man machen kann, wenn new fehlschlägt?(ausser exit)
-
gibt's denn noch irgendwas, was man machen kann, wenn malloc fehlschlägt?
Sofern es sich nicht um wirklich kritische Daten handelt (Erstellen eines Threads, Anlegen von Synchronisationsobjekten, Laden einer DLL etc.): Die aktuelle Aktion abbrechen, alle bisherigen Änderungen zurücknehmen und versuchen zu retten, was noch zu retten ist.
Das hat aber alles nicht wirklich etwas mit Exceptions zu tun; alle diese Probleme hat man auch ohne.
Ich weigere mich zu glauben, dass hier eine Person mitliest, die knallhart mitten in den Tiefen eines Programms
void* data = malloc(size); if(!data) exit(1);
schreiben würde.
T* data = new T; // und wenn's nicht geht, dann wird halt terminate() aufgerufen, na und?
scheint sich ja recht großer Akzeptanz zu erfreuen.
-
godlikebot schrieb:
Wenn ich aber nen dicken try Block mit vielen Befehlen hab und daraus ne exception fange, dann weiss ich doch nicht, wo das Programm stecken geblieben ist.
Das ist ja das, was mich an exceptions etwas stört: Wenn eine exception geworfen wurde, dann ist das Programm (meistens) zum beenden verurteilt, oder seh ich das falsch?Richtig, das siehst du falsch.
Eine Exception ist ein Fehler.
Normalerweise baut ein Programm aber auf dem funktionieren der einzelnen Teile auf.Wenn also jetzt mittem im Rendern einer Szene eine 'Device Lost' Exception fliegt, kann man versuchen das Device wieder herzustellen. Dabei ist es unerheblich ob das Device Lost beim Init, Draw oder Flip aufgetreten ist. Du behandelst es immer gleich: versuchen Device wiederherzustellen.
Du hast Exception nur nicht verstanden
Lies mal die GotW - da gibts einiges interessantes zu Exception.
Der catch Block dient dann nur noch dazu, den Fehler zu loggen oder ne MessageBox auszugeben
Manchmal schon. Denn manchmal kann man auf einen Fehler nicht reagieren, weil er kritisch ist. zB "File Not Found" wenn der User ne Datei öffnen will. Da muss man dann den User fragen was er stattdessen machen will.
Die Lösung wäre eben um jede Funktion einen try/catch Block zu legen, was aber Spaghetti-Code ergibt und eigentlich wenig anders ist als das überprüfen der Rückgabewerte der Funktionen.
Es ist aber unerheblich _welche_ Funktion fehlschlägt.
Es ist dir doch eigentlich egal, ob du ein "Printer Not Ready" beim
Printer printer(LPT1);
oder beim
printer<<"Hallo";
oder beim
printer.setWidth(7);
bekommst.Oder gar ganz woanders.
Es ist unwichtig. Du reagierst ja nicht darauf, dass "printer<<"Hallo";" nicht funktioniert, sondern darauf, dass "Printer Not Ready" passiert ist.
-
OK, so langsam fang ich an, exceptions zu verstehen. Danke erstmal für die Erklärungen.
Shade Of Mine schrieb:
Du hast Exception nur nicht verstanden Lies mal die GotW - da gibts einiges interessantes zu Exception.
Und was sind die GotW?
-
godlikebot schrieb:
Und was sind die GotW?
schonmal gegooglet
GotW (guru of the week) sind 'Artikeln' von Herb Sutter. Er stellt ne Frage, und beantwortet sie dann. Sehr interessant.
Seine beiden Bücher (Mehr) Exceptional C++ basieren recht stark auf den GotW
-
Super! Danke!