Fehler in Typenkonstruktor ohne throw bemerkbar machen?
-
Hallo
Wie der Titel schon sagt, will ich in einem Konstruktor einer Klasse einen Fehler bemerkbar machen. Ich kann kein throw verwenden und Rückgabewerte gibts nicht. Was soll ich tun?
-
Ich kann kein throw verwenden
Warum kannst Du keine Exception werfen? Nimmt mich einfach wunder.
Als Lösung könntest Du eine Init Methode bereitstellen, welche einen Return Wert hat. Die Init Methode übernimmt dann die eigentliche Initialisierung. Das ganze kannst Du in eine Factory Methode packen, sodas kein der Aufruf von Init garantiert ist.
-
theta schrieb:
Warum kannst Du keine Exception werfen?
Vorschrift... (Exception-Handeling ist untersagt)
theta schrieb:
...Factory Methode packen, sodas ein der Aufruf von Init garantiert ist.
Ich mag Init-Funktionen nicht sonderlich, aber egal. Wie geht das?
-
EOutOfResources schrieb:
Ich mag Init-Funktionen nicht sonderlich, aber egal. Wie geht das?
In dem man einen Konstruktor nimmt, der das Objekt stabil konstruiert, aber alle wichtigen Dinge noch nicht setzt und anschließend initialisiert man mittels init Methode mit Rückgabewert das Objekt.
class Foo { Foo () {} ~Foo() {} int init (Argumentliste) { } };
-
~john schrieb:
EOutOfResources schrieb:
Ich mag Init-Funktionen nicht sonderlich, aber egal. Wie geht das?
In dem man einen Konstruktor nimmt, der das Objekt stabil konstruiert, aber alle wichtigen Dinge noch nicht setzt und anschließend initialisiert man mittels init Methode mit Rückgabewert das Objekt.
class Foo { Foo () {} ~Foo() {} int init (Argumentliste) { } };Foo a(); a.init();Gute Idee, danke!
Aber was, wenn ein
kommt undFoo a(); //a nutzenschreibt?
-
Deshalb ist es Schwachfug Exceptionhandling zu verbieten. In Java verbietet man ja auch nicht finally...
Das Objekt muss bei JEDEM methoden aufruf checken ob es in einem ordentlichen State ist. Siehe zB die stream Klassen. Da wird dann das bad-Flag gesetzt und du musst immer per obj.good() schauen ob es in einem guten Status ist.
-
Und was ist mit einem globalen Error-System wie es die WinAPI hat?
-
EOutOfResources schrieb:
Aber was, wenn ein
kommt undFoo a(); //a nutzenschreibt?
"shit happens" Wenn man auf Exceptions verzichtet muß man sich von bestimmten Garantien verabschieden. Beides kann man nicht haben.
-
EOutOfResources schrieb:
Und was ist mit einem globalen Error-System wie es die WinAPI hat?
Das hilft auch nicht weiter, da man explizit nach jedem Konstrukturaufruf das überprüfen müßte. Tut man dies nicht -> Schrott.
-
EOutOfResources schrieb:
Aber was, wenn ein
kommt undFoo a(); //a nutzenschreibt?
Deshalb mein Vorschlag mit der Factory Methode.
Simon
-
Auf die ursprüngliche Frage bezogen...
Ich kenne zwei Möglichkeiten die halbwegs gut funktionieren.
- Man verpasst jeder Klasse eine "GetLastError" Funktion. Ala so:
void foo() { bar b(1, 2, 3); if (b.GetLastError()) FehlerBehandeln(); }- Man gibt jedem ctor eine Referenz auf einen Error-Wert mit. Sieht dann so aus:
void foo() { ErrorCode ec = Success; bar b(1, 2, 3, ec); if (ec != Success) FehlerBehandeln(); }Dabei ist es nicht unüblich, wenn der ctor als erstes den Error-Code prüft, und falls dieser nicht "Success" ist, einfach nichts macht (nichtmal Parameter/Preconditions überprüft) - und den alten Error-Code auch in der Variable stehen lässt.
Dadurch kann man das ganz schön verketten, und muss an weniger Stellen den Fehlercode prüfen.void foo() { ErrorCode ec = Success; bar b(1, 2, 3, ec); baz bz(b, ec); // tut nix wenn der ctor von bar ein problem hatte qux q(b, bz, ec); // tut nix wenn der ctor von bar oder baz ein problem hatte if (ec != Success) FehlerBehandeln(); }----
Empfehlen würde ich es auch nicht, aber wenn es eine Vorgabe ist...
-
Also ehrlich, ihr stellt euch mal wieder an. Die file streams zeigen doch, wie es ohne Exceptions geht, weil C++ Exceptions einfach nichts taugen.
-
@theta: Die Factory Methode (ob als Klassen-Methode oder freie Funktion) allein kann zwar garantieren, dass Ctor + init aufgerufen wird, aber nur nullptr oder Foo* zurückgeben. Was für ein Fehler aufgetreten ist, weiss man aber im nullptr-Fall dadurch nicht.
Hier müsste man dann wieder auf hustbaer's Vorschläge zurückgreifen (getLastError, global, Referenzen), da kann man sich die Factory Methode auch sparen (wenn es nur darum geht, nicht noch um die eigentliche Funktion einer Factory Method).