C++0x checked exceptions?
-
Checked Exceptions funktionieren in C++ nichtmal
template<class Policy> class Foo { private: Policy policy; public: void do_something() { //welche Exception wollen wir denn heute werfen? policy.unknownCode(); } };
-
otze schrieb:
Checked Exceptions funktionieren in C++ nichtmal
template<class Policy> class Foo { private: Policy policy; public: void do_something() { //welche Exception wollen wir denn heute werfen? policy.unknownCode(); } };Was soll den da nicht funktionieren? Zum Kompilezeitpunkt steht fest, ob policy.unknownCode() eine checked Exception wirft oder nicht. Und so wie du es geschrieben hast, würdest du einen Compileerror bekommen, wenn policy.unknownCode() eine checked Exception werfen würde, weil du sie weder fängst noch weiter wirfst.
-
exceptionalcoder schrieb:
Was soll den da nicht funktionieren? Zum Kompilezeitpunkt steht fest, ob policy.unknownCode() eine checked Exception wirft oder nicht. Und so wie du es geschrieben hast, würdest du einen Compileerror bekommen, wenn policy.unknownCode() eine checked Exception werfen würde, weil du sie weder fängst noch weiter wirfst.
Und genau da liegt das Problem. Du musst nachträglich an Foo rumfummeln, um das zum laufen zu kriegen. Oder du musst von Anfang an festlegen, welche Exceptions eine Policy werfen darf und welche nicht. Das wäre dann Kristallkugelprogrammieren vom feinsten, und wiederspräche irgendwie dem Sinn der generischen programmierung.
-
Was hat den das mit "Kristallkugelprogrammieren" zu tun? Du legst doch schon fest, dass Policy eine Methode unknownCode() ohne Parameter haben muss. Was ist da jetzt anders zu dem, dass du noch zusätzlich festlegen würdest, dass diese Methode keine checked Exceptions werfen darf?
Außerdem könnte man ja den Exceptiontyp den do_something weiter wirft oder fängt auch per Template festlegen, falls man das will.
-
Ich weiß gar nicht, wo dein Problem ist. Wenn eine Exception geworfen wird heißt das, dass irgendwas mächtig schiefgelaufen ist und wenn ich nicht weiß, wie ich damit umzugehen habe (<=> ich hab keinen entsprechenden Exceptionhandler implementiert) dann hat das Programm auch gefälligst zu sterben.
exceptionalcoder schrieb:
Was hat den das mit "Kristallkugelprogrammieren" zu tun? Du legst doch schon fest, dass Policy eine Methode unknownCode() ohne Parameter haben muss. Was ist da jetzt anders zu dem, dass du noch zusätzlich festlegen würdest, dass diese Methode keine checked Exceptions werfen darf?
Und welche soll/darf die Funktion werfen? Die eine Policy implementiert Netzwerkstreams, die andere Dateistreams. Die erste wird vermutlich zwischendurch ein „Aye, Host 'blubb' antwortet nicht“ werfen wollen, die zweite „Aye, Datei 'bla' nicht gefunden“. Wenn beide nur CouldNotOpenStream("blubb"/"bla") werfen dürfen hast du einen signifikanten Informationsverlust, du kannst insbesondere keinen sinnvollen Handler implementieren (im ersten Fall eine Hostliste weiter durchgehen oder eine andere Schnittstelle benutzen, im zweiten anderen Pfad ausprobieren).
-
Ist es nicht mittlerweile auch im Java-Lager Konsens, dass Checked Exceptions vielleicht doch nicht so eine gute Idee sins, wie es zuerst schien? Mir war so. Wenn das einer sagt, klingt es jedenfalls in der Regel nicht so, als würde eine großartige Kontroverse angesprochen.
-
Es funktioniert in beiden Fällen gleich.
Jetztclass CouldNotOpenStreamException { public: virtual ~CouldNotOpenStreamException() {}; virtual void ayeJeMiNe() = 0; }; class AyeHostAntwortetNichtException : public CouldNotOpenStreamException { public: virtual ~AyeHostAntwortetNichtException() {}; virtual void ayeJeMiNe(){std::cout << "Au";}; void ayeHost(){std::cout << "Host blaa";}; }; class AyeDateiNichtGefundenException : public CouldNotOpenStreamException { public: virtual ~AyeDateiNichtGefundenException() {}; virtual void ayeJeMiNe(){std::cout << "File blubberbla";}; }; class Policy1 { public: void unknownCode() { throw AyeHostAntwortetNichtException(); } }; int main () { try { Policy1 p1; p1.unknownCode(); } catch (AyeHostAntwortetNichtException &e) { e.ayeHost(); } catch (CouldNotOpenStreamException &e) { e.ayeJeMiNe(); } Policy1 p1; p1.unknownCode(); // möglicher Crash }Mögliche Variante mit Checked Exceptions
class CouldNotOpenStreamException { public: virtual ~CouldNotOpenStreamException() {}; virtual void ayeJeMiNe() = 0; }; class AyeHostAntwortetNichtException : public CouldNotOpenStreamException { public: virtual ~AyeHostAntwortetNichtException() {}; virtual void ayeJeMiNe(){std::cout << "Au";}; void ayeHost(){std::cout << "Host blaa";}; }; class AyeDateiNichtGefundenException : public CouldNotOpenStreamException { public: virtual ~AyeDateiNichtGefundenException() {}; virtual void ayeJeMiNe(){std::cout << "File blubberbla";}; }; class Policy1 { public: void unknownCode() throwsChecked[CouldNotOpenStreamException] { throw AyeHostAntwortetNichtException(); } }; int main () { try { Policy1 p1; p1.unknownCode(); } catch (AyeHostAntwortetNichtException &e) { e.ayeHost(); } catch (CouldNotOpenStreamException &e) { e.ayeJeMiNe(); } Policy1 p1; p1.unknownCode(); // compiler error }Und was wäre jetzt an throwChecked so schlimm (außer meiner Syntax)? Es wäre einfach nur ein Hinweis für den Compiler, dass er eine Fehlermeldung ausgibt, wenn man die Exception nicht fängt. Ich hab hier bis jetzt noch kein richtiges Argument gegen checked Exceptions gehört, sondern immer nur konstruierte Probleme, die nicht wirklich welche sind.
-
Bashar schrieb:
Ist es nicht mittlerweile auch im Java-Lager Konsens, dass Checked Exceptions vielleicht doch nicht so eine gute Idee sins, wie es zuerst schien? Mir war so. Wenn das einer sagt, klingt es jedenfalls in der Regel nicht so, als würde eine großartige Kontroverse angesprochen.
Ja, Checked Exceptions sind out. Viele Frameworks und APIs benutzen mittlerweile vorwiegend RuntimeExceptions (Hibernate ist beispielsweise vor Jahren schon umgestiegen, früher war da auch alles "checked").
Die Nachteile überwiegen einfach. Und im Zweifel kann der Entwickler besser entscheiden, ob eine Exception gefangen, ignoriert oder weitergeworfen werden muss, als der Designer der API oder des Frameworks. Warum sollte man also zu irgendwas gezwungen werden?
-
@exceptionalcoder,
Du hast entweder keine Ahnung was templates sind oder solltest dir den Code von otze nochmals genauer anschauen.Ich bin übrigens auch gegen checked exceptions, aus den bereits genannten Gründen. In Java verwirrt es die Anfänger nur und später geht man die Wände hoch, wenn wegen jedem read oder write ein Fehler wegen einer IOException kommt. Und dann kann man die durch alle Funktionen durchgeben, bis zum GUI ... also throws throws throws throws throws throws ... argl
Gegen eine Warnung oder eine Benachrichtigung hätte ich allerdings nichts dagegen, das wäre dagegen wirklich praktisch! Allerdings ist die Frage, wo und wie wird diese Benachrichtigung erzeugt. Wahrscheinlich schlussendlich zu viel Aufwand für zu wenig.
Grüssli
-
Dravere schrieb:
@exceptionalcoder,
Du hast entweder keine Ahnung was templates sind oder solltest dir den Code von otze nochmals genauer anschauen.Sag was an meinen Aussagen falsch ist und stell hier nicht so leere Behauptungen in den Raum.

-
*sigh*
Code von ozte:
template<class Policy> class Foo { private: Policy policy; public: void do_something() { //welche Exception wollen wir denn heute werfen? policy.unknownCode(); } };Was kann Policy sein? ALLES, es muss nur eine Funktion unknownCode aufweisen. Was diese funktion macht, ist allerdings völlig egal. Die Funktion kann kochen, surfen, reden, plätschern, fahren, fliegen, schlafen, stürzen, setzen, springen, betten, beten, hören, lesen, sprechen, trollen, spielen, usw. [setze irgendein Verb ein]
Merkst du dabei etwas? Es können grundsätzlich unendlich viele unterschiedliche Exceptions fliegen! Wenn du das jetzt auf einmal vereinheitlichen musst, dann widerspricht das dem Designziel der Templates!
Grüssli
-
Selbst das Erzeugen einer Warnung kann bereits kontraproduktiv sein, da dann in größeren Anwendungen eine wahre Flut von Warnungen erzeugt werden würde und du sie ignorieren wirst oder relevante Warnungen in der Menge der unrelevanten gar nicht mehr finden wirst.
Checked Exceptions sind Käse, wenn ich Exceptions nicht fange schmiert mir im schlimmsten Fall die Anwendung ab, wenn ich sie Fange und nicht/falsch behandle kann alles mögliche passieren und kaum reproduzierbar sein.
-
Dravere schrieb:
*sigh*
Code von ozte:
template<class Policy> class Foo { private: Policy policy; public: void do_something() { //welche Exception wollen wir denn heute werfen? policy.unknownCode(); } };Was kann Policy sein? ALLES, es muss nur eine Funktion unknownCode aufweisen. Was diese funktion macht, ist allerdings völlig egal. Die Funktion kann kochen, surfen, reden, plätschern, fahren, fliegen, schlafen, stürzen, setzen, springen, betten, beten, hören, lesen, sprechen, trollen, spielen, usw. [setze irgendein Verb ein]
Merkst du dabei etwas? Es können grundsätzlich unendlich viele unterschiedliche Exceptions fliegen! Wenn du das jetzt auf einmal vereinheitlichen musst, dann widerspricht das dem Designziel der Templates!
Ja ich merk was, dass du nix verstanden hast und dir dabei noch ganz toll vorkommst. Die Einschränkung mit der checked Exception ist nicht größer als die mit dem Namen und den Parametern. Hab ich ja bereits gesagt
exceptionalcoder schrieb:
... Du legst doch schon fest, dass Policy eine Methode unknownCode() ohne Parameter haben muss. Was ist da jetzt anders zu dem, dass du noch zusätzlich festlegen würdest, dass diese Methode keine checked Exceptions werfen darf?
Außerdem könnte man ja den Exceptiontyp den do_something weiter wirft oder fängt auch per Template festlegen, falls man das will.
Exceptionist schrieb:
Selbst das Erzeugen einer Warnung kann bereits kontraproduktiv sein, da dann in größeren Anwendungen eine wahre Flut von Warnungen erzeugt werden würde und du sie ignorieren wirst oder relevante Warnungen in der Menge der unrelevanten gar nicht mehr finden wirst.
Checked Exceptions sind Käse, wenn ich Exceptions nicht fange schmiert mir im schlimmsten Fall die Anwendung ab, wenn ich sie Fange und nicht/falsch behandle kann alles mögliche passieren und kaum reproduzierbar sein.
Sie haben die Arbeit der letzen 5 Stunden verloren, als sie mit unserem Programm auf einem Schreibgeschützendatenträger speichern wollten und unser Programm dabei abgeschmiert ist. Tja Pech, wir wollen nicht soviele Compileerrror oder warings in unserem Programm und dadurch haben wir das leider übersehen.
Und was soll eigentlich immer dieser Schwachsinn mit dem Checked Exceptions sind schlimm, weil man sie falsch behandeln kann? Dann ist alles ist Müll, weil man es falsch verwenden kann.
-
Vielleicht wird die Situation mit den Policies klarer, wenn man ein Beispiel hat, das man direkt kompilieren und ausführen kann. Die Klasse Decision ist in diesem Beispiel der Host für die Policies, und es herrscht dort völlige Unklarheit über die Ausnahmen, die sich Policy-Autoren ausdenken (oder auch weglassen!) könnten:
#include <iostream> using namespace std; class FooPolicy { public: void do_something() { cout << "IMMA CHARGIN' MA LAZER!\n"; throw "SHOOP DA WOOOOOOOOOOOP!"; } }; class BarPolicy { public: void do_something() { cout << "Nothing dangerous here.\n"; } }; template<typename T> class Decision : public T { typedef T do_policy; public: void decide_something() { cout << "Let's see, what we do today...\n"; //Soll hier try/catch erzwungen werden oder nicht??? //Wenn jemand eine neue do_policy mit neuer Ausnahme schreibt, was dann??? do_policy::do_something(); } }; int main() { Decision<FooPolicy> df; Decision<BarPolicy> db; //Entscheidung mit FooPolicy ist gefährlich try { df.decide_something(); } catch (const char *x) { cout << x << endl; } //Entscheidung mit BarPolicy ist ungefährlich db.decide_something(); }
-
exceptionalcoder schrieb:
Sie haben die Arbeit der letzen 5 Stunden verloren, als sie mit unserem Programm auf einem Schreibgeschützendatenträger speichern wollten und unser Programm dabei abgeschmiert ist. Tja Pech, wir wollen nicht soviele Compileerrror oder warings in unserem Programm und dadurch haben wir das leider übersehen.
Denk mal ein bisschen mehr Unix

Mal ganz abgesehen davon, mit normalen Exceptions kann man auch solche Ausnahmen behandeln wenn es sinnvoll ist. Man muss es nicht tun. Und das ist auch gut so. Was wäre denn deiner Meinung nach ein sinnvolles Umgehen mit einer solchen Ausnahme?
-
Exceptionist schrieb:
Selbst das Erzeugen einer Warnung kann bereits kontraproduktiv sein, da dann in größeren Anwendungen eine wahre Flut von Warnungen erzeugt werden würde und du sie ignorieren wirst oder relevante Warnungen in der Menge der unrelevanten gar nicht mehr finden wirst.
Checked Exceptions sind Käse, wenn ich Exceptions nicht fange schmiert mir im schlimmsten Fall die Anwendung ab, wenn ich sie Fange und nicht/falsch behandle kann alles mögliche passieren und kaum reproduzierbar sein.
das nennt man dann wohl "augen zu und durch", oder als marketing-buzzword vielleicht auch "ignorant programming". mit dem ersten argument kann man alle compilerwarnungen ganz abschaffen, und mit dem zweiten jede art von fehlerbehandlung.
es gibt üblicherweise warning-level, die man beim compiler einstellen kann. außerdem kann man idr einzelne warnungen gezielt abschalten.zum thema: checked exceptions können teilweise echt nerven, aber sie sind meiner meinung nach immer noch besser als der jetzige zustand in c++: jede funktion darf einfach alles werfen, ohne dass es irgendwo deklariert werden muss. vc++ (mind. 2003/2005) meckert sogar rum, wenn man nicht-leere exception specifications benutzen will.
wenn man weniger gut dokumentierte libs benutzt, darf man dann den (hoffentlich verfügbaren) quellcode lesen, wenn man alle exceptions gezielt berücksichtigen will.
-
In Ada wird im Vergleich zu anderen Programmiersprachen ziemlich viel vom Compiler erkannt. Checked Exceptions gibt es aber nicht.
Warum? Weil man in Verbindung mit Generics die geworfende Exception nicht immer vorhersehen kann. Man kann zwar auch unbekannte Exceptions fangen, aber mehr als eine Fehlerausgabe kann man daraus auch nicht generieren.
-
exceptionalcoder schrieb:
Ja ich merk was, dass du nix verstanden hast und dir dabei noch ganz toll vorkommst. Die Einschränkung mit der checked Exception ist nicht größer als die mit dem Namen und den Parametern. Hab ich ja bereits gesagt
Mal ganz ehrlich und ich möchte, dass du die Frage wirklich mal beantwortest. Hast du jemals schon in einem grösseren Projekt C++ Templates eingesetzt?
Denn mit dem hier:
exceptionalcoder schrieb:
... Du legst doch schon fest, dass Policy eine Methode unknownCode() ohne Parameter haben muss. Was ist da jetzt anders zu dem, dass du noch zusätzlich festlegen würdest, dass diese Methode keine checked Exceptions werfen darf?
Außerdem könnte man ja den Exceptiontyp den do_something weiter wirft oder fängt auch per Template festlegen, falls man das will.schränkst du die templates wieder deutlich ein. Es ist nicht klar, ob eine Exception geworfen wird oder ob nicht, das ist es nie! Und es sollte auch nicht vorausgesetzt werden, auch nicht per zusätzlichen template parametern. Das macht die Sache höchstens unheimlich kompliziert oder schränkt die Templatefähigkeiten ungeheuer ein.
Zudem, wie so oft in C++ gilt halt das folgende:
Der Programmierer trägt die volle Verantwortung!Wenn du diese Verantwortung nicht willst, dann programmier halt in Java oder sonst einer Sprache, welche dir gefällt.
Grüssli
-
Kreppel schrieb:
Vielleicht wird die Situation mit den Policies klarer, wenn man ein Beispiel hat, das man direkt kompilieren und ausführen kann. Die Klasse Decision ist in diesem Beispiel der Host für die Policies, und es herrscht dort völlige Unklarheit über die Ausnahmen, die sich Policy-Autoren ausdenken (oder auch weglassen!) könnten:
#include <iostream> using namespace std; class FooPolicy { public: void do_something() { cout << "IMMA CHARGIN' MA LAZER!\n"; throw "SHOOP DA WOOOOOOOOOOOP!"; } }; class BarPolicy { public: void do_something() { cout << "Nothing dangerous here.\n"; } }; template<typename T> class Decision : public T { typedef T do_policy; public: void decide_something() { cout << "Let's see, what we do today...\n"; //Soll hier try/catch erzwungen werden oder nicht??? //Wenn jemand eine neue do_policy mit neuer Ausnahme schreibt, was dann??? do_policy::do_something(); } }; int main() { Decision<FooPolicy> df; Decision<BarPolicy> db; //Entscheidung mit FooPolicy ist gefährlich try { df.decide_something(); } catch (const char *x) { cout << x << endl; } //Entscheidung mit BarPolicy ist ungefährlich db.decide_something(); }Also erst mal war die Aussage von otze, dass checked Exceptions in C++ nicht funktionieren. Und unter nicht funktionieren versteh ich, dass es ein technische Problem mit dem Compiler gibt bei dem das nicht geht, aber sowas zeigt dein Beispiel nicht. Das man irgendein For-Bar-Beispiel bauen kann bei dem es nicht sinnvoll ist eine checked Exception zu fangen weil sie eigentlich gar nie geworfen wird ist mir auch klar. Das hat aber wenig mit der ganzen Sache zu tun. Wenn eine Methode eine checked Exception wirft, dann muss das auch in der Deklaration angegeben werden. Dann kann der Compiler sagen: Hallo die Methode sagt, sie wirft eine Exception die du fangen musst, aber tust es nicht. Ob in der Methode wirklich Code steht der eine Exception wirft oder nicht ist völlig egal. Das ist das gleiche wie wenn du sagst Parameter für Methoden funktionieren nicht, weil ich irgendwo was mit Templates schreiben kann und da noch nicht weiß welche Parameter ein anderer Programmierer für seine Methode braucht oder ob er nen Errorcode zurückgibt.
Dravere schrieb:
exceptionalcoder schrieb:
Ja ich merk was, dass du nix verstanden hast und dir dabei noch ganz toll vorkommst. Die Einschränkung mit der checked Exception ist nicht größer als die mit dem Namen und den Parametern. Hab ich ja bereits gesagt
Mal ganz ehrlich und ich möchte, dass du die Frage wirklich mal beantwortest. Hast du jemals schon in einem grösseren Projekt C++ Templates eingesetzt?
Ja
Denn mit dem hier:
exceptionalcoder schrieb:
... Du legst doch schon fest, dass Policy eine Methode unknownCode() ohne Parameter haben muss. Was ist da jetzt anders zu dem, dass du noch zusätzlich festlegen würdest, dass diese Methode keine checked Exceptions werfen darf?
Außerdem könnte man ja den Exceptiontyp den do_something weiter wirft oder fängt auch per Template festlegen, falls man das will.schränkst du die templates wieder deutlich ein. Es ist nicht klar, ob eine Exception geworfen wird oder ob nicht, das ist es nie! Und es sollte auch nicht vorausgesetzt werden, auch nicht per zusätzlichen template parametern. Das macht die Sache höchstens unheimlich kompliziert oder schränkt die Templatefähigkeiten ungeheuer ein.
Lies das mit der Methoden Deklaration, was ich zu Kreppels Beispiel geschrieben hab
Zudem, wie so oft in C++ gilt halt das folgende:
Der Programmierer trägt die volle Verantwortung!Und darum gibt es in C++ überhaupt keine Typsicherheit und sowas...

Wenn du diese Verantwortung nicht willst, dann programmier halt in Java oder sonst einer Sprache, welche dir gefällt.
Lass doch einfach mal diese dämlichen und schwachsinnigen Sprüche und erzähl mir nicht was ich deiner Meinung nach kann und machen soll, sondern bleib beim technischen.
-
exceptionalcoder schrieb:
Also erst mal war die Aussage von otze, dass checked Exceptions in C++ nicht funktionieren. Und unter nicht funktionieren versteh ich, dass es ein technische Problem mit dem Compiler gibt bei dem das nicht geht, aber sowas zeigt dein Beispiel nicht.
Es ging darum, dass sie nicht in Verbindung mit dem beliebten Policy-Based Design funktionieren.
Man bietet eine Host-Klasse in einer Bibliothek an und will später nichts mehr daran machen müssen und erst Recht sollen die Kunden der Bibliothek die Implementierung der Host-Klasse nicht anpacken müssen. Die Kunden können aber selbst Policies schreiben, die der Host-Klasse per Template-Parameter übergeben werden, denn genau das ist der Sinn von Policy-Based Design. Wenn der Kunde in seiner Policy nun aber plötzlich eine unbekannte Exception wirft, kann sie ja von der ihm zur Verfügung gestellten Host-Klasse überhaupt nicht beachtet werden, weil er sie sich gerade ausgedacht hat. Dann gibt es Compilerfehler, und er soll die womöglich teuer gekaufte Host-Klasse verändern müssen, damit seine neue Exception dort auch noch abgefangen werden kann?