Konstruktor auch ohne Erfolg realisierbar?
-
Danke für die Beiträge. Ich werd mal etwas konkreter:
1. Hauptprogramm möchte ein Objekt der Klasse Test erzeugen.
2. Test versucht eine Schnittstelle zu konfigurieren. Dabei Misserfolg soll Test es noch x-mal versuchen. Danach muss Test den Misserfolg weitergeben (z.B. Rückgabewert).
3. Wenn Hauptprogramm den Misserfolg mitbekommt, soll das Objekt der Klasse Test gelöscht werden und mit einer Fehlerroutine fortgefahren werden.Bei meiner Methode:
1. Objekt erzeugen
2. Objekt-initroutine bei bedarf bis zu x mal aufrufen
3. wenn nicht erfolgreich -> deleteDie Idee mit der factory hat sich gut angehört. Wie würde diese aussehen?
so in etwa?:
1. Objekt erzeugen (über factoryklasse?!)
2. Factory behandelt das ganze wie oben(also objekt erzeugen + x-mal init()), bei Erfolg gibt sie Objekt zurück, bei Misserfolg NULL.
2. prüfe auf Objekt = NULL
-
[Edit]
@Simon2:
[/Edit]
Deswegen hab ich ja auch geschrieben, er solle so tun, als ob mein Beitrag über dem von CStoll steht. Ich wollte die Exceptionvariante nicht kritisieren oder meine als die bessere hinstellen.
Ich persönlich mag Exceptions nicht. Ich hab's mir so angewöhnt. Und vergesse eigentlich auch keine Überprüfung.
Ich denke mal, dass es halt wirklich nur eine Sache der Gewöhnung ist.
-
Ja also Exceptions würde ich auch gerne vermeiden. Bin auch kein Freund davon. Wenns ohne geht hät ich nix gegen

-
Maffe001 schrieb:
Ich persönlich mag Exceptions nicht. Ich hab's mir so angewöhnt. Und vergesse eigentlich auch keine Überprüfung.
"Eigentlich nie" heißt "einmal in zwei Stunden", ja ja. Aber Dummheit, Trägheit und Sturheit sind eben nicht totzukriegen.

-
Gustav Hummel schrieb:
Die Idee mit der factory hat sich gut angehört. Wie würde diese aussehen?
so in etwa?:
1. Objekt erzeugen (über factoryklasse?!)
2. Factory behandelt das ganze wie oben(also objekt erzeugen + x-mal init()), bei Erfolg gibt sie Objekt zurück, bei Misserfolg NULL.
2. prüfe auf Objekt = NULLso ungefähr. das grundprinzip ist, dass die factory alle nötigen daten besorgt und sobald sie vorliegen, ein objekt erzeugt. d.h. deine klasse braucht keinen init ballast und auch kein exception handling etc. das macht alles die factory, und wenn das erzeugen erfolgreich möglich war, liefert sie nen schlankes, vollständiges objekt zurück. wenn also die daten nicht besorgt werden konnten, wurde auch zu keinem zeitpunkt versucht, ein objekt anzulegen.
-
@Kenner....:
Was soll ich da jetzt zu sagen?
Wie gut, dass jeder seine Meinung haben darf.Nur mal so: Ich kann kein "nie" bei mir entdecken.
Getreu nach dem Motto: "Nobody is perfect.", vergess ich die Überprüfung auch mal. Aber es ist die Ausnahme. 
-
Maffe001 schrieb:
Nur mal so: Ich kann kein "nie" bei mir entdecken.
Getreu nach dem Motto: "Nobody is perfect.", vergess ich die Überprüfung auch mal. Aber es ist die Ausnahme. 
Aber einen guten Grund, Exceptions nicht zu benutzen brauchst du offensichtlich auch nicht. Da müsstest du nicht ständig sinnlose Überprüfungen von sinnlosen Objekten durchführen...

-
@Kenner...:
Also wenn du rumtrollen willst, warum tust du's nicht woanders?
Du magst wahrscheinlich keinen Rosenkohl und trotzdem werd ich nicht versuchen ihn dir aufzuzwingen. Deine Begründung, warum du ihn nicht magst, wird eher dürftig ausfallen. Gut aber das ist dein Ding.@alle anderen:
Sorry, dass ich da nochmal drauf eingestiegen bin. Intolleranz find ich einfach nur....
Damit sind dann auch meine Reaktionen auf "Kenner" beendet.
-
Ich finde die Variante besser, wo im Konstruktor kein Fehler erzeugt werden kann

-
Auch wenn ich dir nicht das Programmieren ohne Exceptions ausreden will, möchte ich hier nur mal die Gründe die für eine Exception sprechen hinstellen:
a) Wenn man Standardkonform programmiert, wird man zwangsweise Exceptions behandeln müssen (die STL wirft Exceptions, ebenso wie new).
b) Exceptions sind Ausnahmefälle, keine Regeln, der Rückgabeparameter einer Funktion sollte so gewählt werden das er die Regelfälle sinnvoll abdeckt.
c) Rückgabewerte darf man nicht vergessen, Exceptions kann man nicht vergessen (Sonst knallt es, wo beim Rückgabewert das Programm einfach irgendwas - ggf. sehr verkehrtes/schlimmes - tut).
d) Exceptions muss man nicht zwingend am Ort des Auftretens behandeln, Rückgabewerte schon.
e) Mit Exceptionhandling und Smartpointern kann man inkonsistente Daten nach einen Konstruktoraufruf leichter behandeln [bin kein Fan von der Ungarischen Notation, aber für die kurzform hier besser: m_ap=> Autopointer/Smartpointer als Member]:Fall 1 mit Smartpointer&Exceptionhandling
Klasse::Klasse() : m_apObjekt1(new Objekt1()), m_apObjekt2(new Objekt2()), m_apObjekt3(new Objekt3()) { }Wenn nun bei der Objektanlage irgendeines Teilobjektes eine Exception auftritt, so werden alle vorherigen gelöscht, und der Konstruktor erstellt kein Objekt (sprich: kein Objekt oder ein Konsistentes).
Versuch das mal ohne Exceptionhandling mit wenigen Codezeilen sinnvoll nachzubauen (noch dazu wenn vielleicht noch mehr Teilobjekte dazukommen).
cu André
-
ich bin kein fan von exceptions.
try { // gewaltiger, ellenlanger code } catch(...){} // weiter gehtssie verleiten zu lazy coding. gedanken darüber machen, ob auch alles klappt? input überprüfen? ach egal, wenn was schief geht, wird schon irgendwo ne exception fliegen, die man ja abfangen kann.
-
Maffe001 schrieb:
[Edit]
...Ich wollte die Exceptionvariante nicht kritisieren oder meine als die bessere hinstellen....Das war mir klar ... aber ich wollte Deine Variante kritisieren und die Exceptionvariante als die bessere hinstellen...

Was hast Du gegen exceptions ? Die sind genau für diesen Fall gemacht.
Ach ja: D.h. Du fragst auch bei printf() immer den Returncode ab ?
Gruß,
Simon2.
-
thordk schrieb:
...sie verleiten zu lazy coding....
Inwieweit das ?

Ich würde eher sagen: Mit exceptions kann man sich auf das Wesentliche konzentrieren ... versuch mal, ohne exceptions "exceptions safety" (= ein Kriterium einer stabilen Schnittstelle) umzusetzen ... da wirst Du Dir die Finger brechen - und letztlich eine Art exceptions (nur mit mehr Overhead) selbst programmieren.Gruß,
Simon2.
-
thordk schrieb:
sie verleiten zu lazy coding.
Wenn du ohne Exceptions arbeitest, ist das noch schlimmer. Vor allem wird dich niemand darauf aufmerksam machen, wenn du vergessen hast, einen Fehlerwert zu überprüfen (und was dein Programm in einem fehlerhaften Zustand macht, kann dir niemand sagen) - Exceptions fliegen dir ziemlich lautstark um die Ohren, wenn du versuchst, sie zu ignorieren.
-
LOL Nein ich überprüfe nicht den Return von "printf".
Ich überprüf ihn immer bei Sachen, die ich selbst geschrieben habe. Den traue ich natürlich nicht so ganz. Vielleicht ist diese Einstellung wirklich etwas blauäugig.Hmpf, ich seh schon. Ich werd meine Einstellung zu Exceptions überdenken müssen. Allerdings bin ich immernoch der Meinung, dass man bei Objekten, die man nicht richtig initialisiert bekommt auch weiterhin mit Rückgabewerten arbeiten kann. Wenn euch jetzt ein Gegenbeispiel einfällt, dass sich nur mit Exceptions behandeln lässt, dann immer her damit.

[Edit]Ui, ich hab grad den Beitrag von asc entdeckt. Sorry, ging in der Aufregung unter. Dann vergesst, was ich gesagt habe. Die Gründe leuchten ein. Gut ich werde nochmal darüber meditieren und mich mit Exceptions anfreunden. :D[/Edit]
-
Und wie soll ein Konstruktor etwas als Rückgabewert übergeben? Das einzige, was der zurückgeben kann, ist ein fertig konstruiertes Objekt, also bleibt als Alternative zu einer Exception nur, this in einen Zombie-Status zu versetzen. Und wenn jede Methode erst überprüfen muß, ob sie auf ein intaktes Objekt angewendet wurde, bremst du damit dein gesamtes Programm unnötig aus.
-
CStoll schrieb:
Und wie soll ein Konstruktor etwas als Rückgabewert übergeben? Das einzige, was der zurückgeben kann, ist ein fertig konstruiertes Objekt, also bleibt als Alternative zu einer Exception nur, this in einen Zombie-Status zu versetzen. Und wenn jede Methode erst überprüfen muß, ob sie auf ein intaktes Objekt angewendet wurde, bremst du damit dein gesamtes Programm unnötig aus.
Du würdest fstream anders realisieren?
-
delete this;
-
class MyClass { public: MyClass(int &riRes) { if (....) { riRes = -1; return; } } };Ist also nur ein Quasirückgabewert. Deswegen hab ich's auch weiter oben mit "" geschrieben.
-
@Bashar: Nicht unbedingt - bei den IO-Streams kann es ja auch vorkommen, daß ein bereits existierendes Objekt später ungültig wird, also ist der inaktiv-Status sowieso notwendig. Aber bei Objekten, die nach einer erfolgreichen Initialisierung (aka Erschaffung) gültig bleiben, kostet es nur Zeit und Platz mitzuschreiben, ob sie nutzbar sind.
@Maffe: Also da ist die Exception-Variante auf jeden Fall eleganter und sicherer:
int dummy;//damit der Ctor glücklich ist MyClass test(dummy); test.do_something();Wenn du vergisst, das Ergebnis zu kontrollieren (und kein Compiler der Welt wird dich darauf aufmerksam machen, daß dort etwas wichtiges zurückgekommen ist), arbeitest du mit einem kaputten Objekt.
Im Gegensatz dazu:
try { MyClass test; test.do_something(); } catch(...) {...}Wenn der Ctor eine Exception geworfen hat, springt das Programm ohne Umwege zum catch-Block - also werden auch alle Anweisungen umgangen, die mit dem (jetzt unbrauchbaren) Objekt arbeiten wollten.