Zum Inhalt springen

Sich wieder selbst zerstörende Objekte


Schlitzauge

Empfohlene Beiträge

Hallo COM,

ich habe mal eine Frage zu Klassen-Objekten.

Wenn ich mir eine string-Variable anlege und ihr einen numerischen Wert zuweise, etwa so:

string test = 40.5;

, würde entweder a.) schon der Kompiler herummeckern oder b.) es würde eine Exception während der Laufzeit ausgeführt werden.

1.)

Jetzt habe ich eine selbstgeschriebene Klasse "CBruch(int Z,int N), welche es ermöglicht, mit Brüchen zu rechnen.

Wie wir aber alle wissen, gibt es keine Brüche, wie "4/0", da Division durch 0.

Ich möchte etwas Derartiges realisieren, dass, wenn ich ein Klassenobjekt mit einem Nenner-Initialisierungswert 0 erzeuge, dass das Objekt sich von selbst wieder zerstört (sprich Speicher frei gibt) und ggfl. sogar eine eigene Exception auslöst.

Meine Frage dazu, wie realisiert man das? Ich weiß, dass der Destruktor dazu verwendet wird, den Speicher eines Objektes bei dessen Zerstörung wieder freizugeben. Kann man denn den Desktruktor bereits im Konstruktor auslösen, sodass das Objekt erst garnicht erzeugt wird, wenn man diesem als Nenner-Variable den Wert 0 zuweisen möchte?

Eine Exception auszulösen, stellt für mich jetzt nicht DAS Problem dar, sondern, wie ich dafür sorge, dass der Speicher des fehlerhaft initialisierten Wertes, automatisch wieder freigegeben wird, halt ein sich selbst zerstörendes Objekt.

2.)

Gibt es auch eine Möglichkeit, den Kompiler bei einem solchen Fall, bereits daran zu hindern, zu kompilieren, am besten mit eigener Fehlermeldung für und an den Kompiler, sodass es zu einem solchen Initialisierungsfehler erst garnicht kommen kann?

Ich meine das so, wie beim obigen Beispiel mit string und numerischer Wertzuweisung.

Da bricht i.d.R. der Kompiler ja auch den Kompiliervorgang mit entsprechender Fehlermeldung ab. Kann man dem Kompiler denn mitteilen, dass er nicht mehr weiter kompilieren soll, wenn man ein Klassenobjekt von CBruch mit Nenner = 0, initialisieren möchte, sprich, dass dieser dann mit entsprechender Fehlermeldung abbricht.

3.) Was gibt es noch alles für Möglichkeiten, codeseitig einem Kompiler am kompilieren zu hindern? (Außer Syntax-Fehler zu provozieren!)

THX schonmal im Voraus!!!

Grüße

Schlitzauge :):):)

Link zu diesem Kommentar
Auf anderen Seiten teilen

zu 1.) Eine Exception auszulösen, ist mir schon klar. Mir geht es aber darum, dass das erzeugte Objekt, dann auch wieder restlos zerstört wird. Denn auch bei ausgelöster Exception, besteht es ja noch weiterhin.

zu 2.) Kannst Du oder auch wer anders, mir ein paar gute Quellen zu asserts geben. Insb. bin ich an Asserts zur Laufzeit, als auch zur Kompilierzeit interessiert.

3.) Kann mich auch mal jemand zu Verifiy() und Assert_Valid() aufklären? Ist ja Microsoft-spezifisch.

Gibts sowas auch für Nicht-Microsoft-Kompiler- bzw. OS´s?

Grüße

Schlitzauge :-)

Link zu diesem Kommentar
Auf anderen Seiten teilen

1.

if(z==0) throw Exception();
2.
try{/*whatev*/}catch(Exception e){objekt.~CBruch();}finally{/*whatev*/}

3. Ein kurzer Blick in die C++ ref hätte dir das btw. auch beantwortet.

4. Benenn deine Variablen Anständig und CBruch(int, int) ist keine Klasse, sondern maximal der Konstruktor. Die Klasse ist CBruch, wenn überhaupt.

5. Ich behaupte einfach mal ohne deinen Code zu kennen, deine Instanz der Klasse CBruch wird innerhalb einer Funktion erzeugt. Nach ablauf der Funktion ist es nicht mehr gültig und wird automatisch zerstört.

Link zu diesem Kommentar
Auf anderen Seiten teilen

zu 1 und 2.)

Wie gesagt, Exceptions auszulösen, ist nicht das Problem.

Gut, im Catch-Zweig den Destruktor auszulösen wäre eine Variante, vlt. auch die einzige, wie mir mittlerweile erscheint.

Da werd ich wohl um asserts nicht drumherum kommen.

Mich stört es halt, dass man die Ausnahmebehandlung und Zerstörung außerhalb vornehmen muss.

Gibt es keine Möglichkeit, dass ein Objekt sich selber zerstören kann?

zu 4.) (was es nicht gibt ;)):

Ich weiß. Sollte nur verdeutlichen, welche Übergabeparameter ein zu erzeugendes Objekt der Klasse CBruch haben muss. Daraus herzuleiten, wie die Klasse ausschaut und aufgebaut ist, denke ich, sieht damit wohl jeder.

zu 5.) (was es ebenfalls nicht gibt ;)):

Situationsbedingt. Natürlich wird jeglicher Speicher bei Austritt aus seinem Block / Funktionsbereich, automatisiert freigegeben. Das Trifft aber nunmal nicht immer zu. Außerdem wären da ja noch dynamische Objekte, delete hin oder her. Ich möchte halt gerne eine komfortablere Möglichkeit realisieren, sprich dem Programmierer die Arbeit abnehmen, fehlerhaft erzeugte Objekte, sofort wieder zu zerstören, etc.

Grüße

Schlitzauge :)

Bearbeitet von Schlitzauge
Link zu diesem Kommentar
Auf anderen Seiten teilen

Sich selbst zerstören? Speicher einer Funktion zum Zeitpunkt der Lauftzeit (dieser Funtkion) wieder freizugeben? Halt ich jetzt nur sehr bedingt für nen Plan, dass man sich damit ins Knie schießt sollte eigentlich selbstverständlich sein.

4) Genau dieser Aufbau könnte relevant sein, vorallem da du von korrekt erzeugten/fehlerhaft erzeugten Objekten sprichst, Wenn im Konsturktor einfach nur ein "Zähler = z", "Nenner = n" ausgeführt werden ist das ding trotzdem völlig korrekt gebaut, die hypothetische Methode "CBruch::divide()" fliegt dir dann halt um die Ohren. Vom Korrekten Anlegen halber Objekte hab ich noch nicht gehört, entweder es klappt oder es klappt nicht. 0 oder 1.

5) Wann nicht? Ein Objekt kann noch so dynamisch sein, es ist trotzdem nur innerhalb seines Scopes gültig.

Link zu diesem Kommentar
Auf anderen Seiten teilen

4) Genau dieser Aufbau könnte relevant sein, vorallem da du von korrekt erzeugten/fehlerhaft erzeugten Objekten sprichst, Wenn im Konsturktor einfach nur ein "Zähler = z", "Nenner = n" ausgeführt werden ist das ding trotzdem völlig korrekt gebaut, die hypothetische Methode "CBruch::divide()" fliegt dir dann halt um die Ohren. Vom Korrekten Anlegen halber Objekte hab ich noch nicht gehört, entweder es klappt oder es klappt nicht. 0 oder 1.

Ditt is ja der Witz an der Ganzen Sache. Das Objekt solle sich ja selbst zerstören, wenn man es z.B. so initialisiert

CBruch(4,0);

D.h. es soll dann erst garnicht weiter existieren. Einer string-Variablen, kann ich schließlich auch keinen numerischen Wert zuweisen. Das Problem hier ist nunmal aber nicht der Unterschied der Datentypen, sondern innerhalb einer Datentyps-Art, nämlich int, den Wert 0 für den Nenner zu verbieten. Das Objekt mit Nenner 0, sollte dann allerdings nicht weiter existieren, sondern terminiert werden. Ich möchte aber nicht den Programmierer die Arbeit aufzwingen, den Fehler durch eigene Ausnahmebehandlung, abzufangen. Er solle nur das Objekt anlegen und im Falle von Nenner = 0, darauf aufmerksam gemacht werden, dass dies eine ungültige Initialisierung ist und das Objekt zerstört wird. Sprich Zerstörung mit anschließender Fehlermeldung.

Da scheinen Asserts wohl doch die bessere Variante zu sein.

Hätt ja sein können, dass es doch sich selbst zerstörende Objekte gibt.

Falls es möglich sein sollte, wäre es super, wenn mir jemand sagen könnte wie.

Grüße

Schlitzauge :):):):)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Definiere bitte "crank"?

Und konstruktiv ist das auch nicht!

Klischeepunk hat mir sehr weitergeholfen, also was das andere Problem in diesem Thread anbelangt. Anscheind lässt sich die eine Idee so aber nicht realisieren. Ich lass es trotzdem mal im Raum stehen. Vlt. findet sich ja jemand, der die Idee dennoch umsetzen kann.

Was aber soll daran soooo crank sein, ein sinnloses Objekt, also sinnlos verbrauchten Speicher, wieder freizugeben.

Ein Bruch mit Nenner 0, macht schließlich keinen Sinn. Die Möglichkeit, dass jemand einen solchen aber mal initialisieren möchte, und sei es ausversehen, oder Aufgrund einer Rechenoperation, besteht dennoch. Logische und beste Folge wäre da, dass Objekt wieder zu terminieren oder nicht? Das ganze manuell abzufangen, ginge, wiederspricht meiner Meinung nach aber den Prinzipien der Automatisierung. Man schreibt für sich und andere schließlich Bibliotheken und Frameworks, um einiges an Tipp-Arbeit zu ersparen. Ein sich selbst zerstörendes Objekt, wäre also garnicht mal CRANK. Ich bin natürlich für weitere Lösungsansätze offen.

Grüße

Schlitzauge :) :) :) :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das Problem ist doch mit einer einfachen Exception und eines try-catch Blocks gelöst. Wenn der Konstruktor die Daten bekommt und eben bei fehlerhaften Daten eine Exception wirft, dann kann man diese mit try-catch abfangen. Entweder mache ich das mit einer lokalen Variablen, sobald der Block verlassen wird, ist die Variable vom Stack verschwunden (bzw. wenn man sie überschreibt). Andernfalls kann ich das Objekt auf den Heap legen und eben im try-catch Block feststellen, ob es korrekt initialisiert wurde. Wenn man es richtig macht, prüft man im Konstruktor bevor Speicher allokiert wird ob alle Daten korrekt sind, d.h. tritt die Exception aus, sind alle lokalen Stackvariablen des Objektes auch vernichtet, da das Objekt out-of-scope geht. Innerhalb des try-catch Blocks weise ich einer Zeigervariablen den Zeiger des Objektes zu, so dass man prüfen kann, ob der Zeiger null ist, wenn ja, wurde das Objekt nicht richtig erzeugt. Bei Ablage auf dem Heap muss man natürlich von der übergeordneten Struktur dafür Sorge tragen, dass der Speicher des Objektes auch wieder frei gegeben wird

Link zu diesem Kommentar
Auf anderen Seiten teilen

Was aber soll daran soooo crank sein, ein sinnloses Objekt, also sinnlos verbrauchten Speicher, wieder freizugeben.

Ein Bruch mit Nenner 0, macht schließlich keinen Sinn. Die Möglichkeit, dass jemand einen solchen aber mal initialisieren möchte, und sei es ausversehen, oder Aufgrund einer Rechenoperation, besteht dennoch. Logische und beste Folge wäre da, dass Objekt wieder zu terminieren oder nicht? Das ganze manuell abzufangen, ginge, wiederspricht meiner Meinung nach aber den Prinzipien der Automatisierung. Man schreibt für sich und andere schließlich Bibliotheken und Frameworks, um einiges an Tipp-Arbeit zu ersparen. Ein sich selbst zerstörendes Objekt, wäre also garnicht mal CRANK. Ich bin natürlich für weitere Lösungsansätze offen.

An der Idee ein sinnloses Objekt freizugeben ist nichts krank, dies allerdings in einem Bereich zu tun, in dem das Objekt existiert und auf den Gerade zugegriffen wird, hat schon etwas krankes. Wenn ich in eine Funktion springe und ihr gleichzeitig den Speicher wegnehme, dann dürfte es mit recht hoher Wahrscheinlichkeit dazu führen, dass dir dein Stack mit Pauken und Trompeten um die Ohren fliegt.

Nach ner Diskussion mit nem Kumpel außerdem noch: Eine Exception hat im Konstruktor nichts, aber auch gar nichts verloren. Der Konstruktor hat _immer_ korrekt zu terminieren. Logischerweise. Wir wollen unsere Variablen korrekt initialisieren und das Objekt Gültigkeit erlangen lassen. Sind nacher unerwarteterweise korrupte Daten drin, fangen wir das lieber in eine .IsValid()/.AssertValid() Methode ab, bauen uns Validitätsprüfungen an den Anfang der Methode oder aber, lassen das Objekt in ner Factory erstellen, wo wir bereits vor erstellen des Objektes die Validität der Übergebenen Parameter prüfen können. Hierzu:

Factory method pattern

Ansonsten würde ich flashpixx Aussage weiter verfolgen: Membermethode Exception werfen lassen, sollten wir unerwarteteerweise doch murks im Objekt stehen lassen und vllt im Konstruktor "Ausnahmenwerte" definieren. (bspw. Erwartete eingabe ist immer >= 0 wäre -1 eine Option eine Ausnahme zu kennzeichnen, seis nun "kein wert erhalten" oder "something has gone terribly wrong") .

Zu guter letzt: Dein Objekt "gehört" immer jemand anders, nie sich selbst, von daher kann der Besitzer sich auch darum kümmern, dass er seinen Speicher wieder sauber hinterlässt. - Seis die Factory, die main() oder ein anderes Objekt oder auch nur Methode. Undefinierte Zustände sind jederzeit vermieden, also sollte es auch kein Problem darstellen das Objekt sauber zu zerstören. (erst danach beginnt undefiniertes verhalten ;))

Link zu diesem Kommentar
Auf anderen Seiten teilen

Achja anmerkung noch: Wenn du für andere Libs, Frameworks oder was auch immer gestaltest - dann bau ne saubere Schnittstelle, die sich um das Objekt kümmert, dann muss dein gegenüber absolut nichts vom Objekt wissen und du gibst nur ein true/false zurück ob das ding korrekt erstellt wurde oder nicht (aus deiner Interfacemethode, NICHT dem Objektkonstruktor!)

Dein "Nutzer" kann dann schlichtweg if(createObjekt(objBuf)) { /*Fange etwas damit an */ } machen und ist happy, oder wegen mir auch

Objekt *objBuf = NULL; 

objBuf = createObjekt(z, n); 

if(objBuf != NULL) {/***** you dolphin and whale*/}


Objekt *createObjekt(int z, int n) 

{

/*Ausnahme Abfangen*/

if(n == 0)

{ return NULL; }

/* ... */

}

Irgendetwas in die Richtung. Wichtig ist nicht ob ich ne Zeile mehr oder weniger tippen muss, sondern ob ich was vernünftiges aus deiner "BlackBox" zurück erhalte. Und vernünftig bedeutet etwas,das entweder Gültig ist und im Fehlerfall auch Fehler wirft, oder etwas dem ich ansehe dass irgendwas gründlich schief gegangen ist.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nach ner Diskussion mit nem Kumpel außerdem noch: Eine Exception hat im Konstruktor nichts, aber auch gar nichts verloren. Der Konstruktor hat _immer_ korrekt zu terminieren. Logischerweise. Wir wollen unsere Variablen korrekt initialisieren und das Objekt Gültigkeit erlangen lassen.

Das sehe ich unter Umständen anders. Z.B. kann java.lang.String bei der Übergabe eines null Objektes eine NullPointerException werfen, d.h. in diesem Fall wirft der Konstruktor die Exception. Was würde dagegen sprechen, dass der Konstruktor die übergebenen Parameter prüft und wenn diese nicht korrekt sind eine Exception wirft. Wenn sie korrekt sind, geht die Initialisierung weiter so dass der Konstruktor terminieren kann. Wird die Exception geworfen, dann sind die Membervariablen auch nicht initialisiert, entweder das Programm terminiert, d.h. bei einer Referenz auf den Stack hat der Compiler entsprechend den Code generiert, so dass der Speicher freigegeben wird oder ich fange die Exception ab und anhand der entsprechenden Objektvariablen wird auch der Speicher des Stacks beim Verlassen des Blocks frei gegeben. Wenn man mit Zeigern arbeitet, dann muss man natürlich im catch-Block entsprechend selbst aufräumen.

Das genannte bezieht sich letztendlich auf den genannten Besitzer. Objekte die auf dem Stack platziert werden, darum kümmert sich der Compiler, bei Objekten auf dem Heap muss ich mich selbst darum kümmern. Durch die entsprechende Blockstruktur kann der Compiler erkennen, wann ein Objekt out-of-scope geht und daher wird er dann den Destruktor des Objektes aufrufen. D.h. wenn ich meine Variable innerhalb des try-Blocks deklariere wird dort auch der Konstruktor aufgerufen, d.h. sobald der try-Block verlassen wird, wurde das Objekt vom Stack entfernt. Natürlich muss man darauf achten, dass man eben im Konstruktor die richtige Reihenfolge achten, wenn ich natürlich erst eine Heapreferenz im Konstruktor erzeuge und dann die Exception werfe, dann muss ich mir Gedanken machen, wie ich die Referenz entfernt bekomme.

Das Problem bezügl. der Asserts ist, dass man mit Exception anders arbeitet. Man kann als Benutzer der Klasse die Exception fangen und verarbeiten. Letztendlich ist ein Objekt ein Automat, der immer in einem definierten Zustand sein soll. Eine Exception kann man als Fehlerzustand auffassen, rein formal gibt es Pre- und Postconditions, d.h. Anforderungen, die vor bzw nach der Methodenausführung gelten müssen, d.h. in diesem Fall muss als Precondition gelten, dass Nenner != 0 sein muss, d.h. der Konstruktor darf erst gar nicht durchlaufen werden, denn sonst wäre das Objekt in einem Zustand. Nachdem der Konstruktor terminiert würde als Postcondition der Nenner != 0 gelten. Was während der Ausführung geschieht ist nicht relevant (analog zur Schleifeninvarianten).

Undefinierte Zustände sind jederzeit vermieden, also sollte es auch kein Problem darstellen das Objekt sauber zu zerstören. (erst danach beginnt undefiniertes verhalten ;))

Das ist der oben genannte Punkt. Wie man diesen erreicht muss man problemspezifisch überlegen. In manchen Fällen ist es sinnvoller den Konstruktor terminieren zu lassen und durch eine entsprechende Membervariable den Zustand kenntlich zu machen, führt aber natürlich dazu, dass man dieses als Speicherplatz berücksichtigen muss und ggf. wenn eine Methode mehrfach aufgerufen wird, bei jedem Methodenaufruf geprüft werden muss, was letztendlich Aufwand bedeutet. Andernfalls kann man mit Asserts manche Probleme abfangen oder eben, wenn es sich um dynamische Daten handelt eine Exception benutzen

Link zu diesem Kommentar
Auf anderen Seiten teilen

Natürlich muss man darauf achten, dass man eben im Konstruktor die richtige Reihenfolge achten, wenn ich natürlich erst eine Heapreferenz im Konstruktor erzeuge und dann die Exception werfe, dann muss ich mir Gedanken machen, wie ich die Referenz entfernt bekomme.

Wenn ich mich richtig erinner meckert bei Java netterweise auch der Compiler, wenn ich ne Exception nicht behandel, mein Compiler übersetzt folgendes allerdings Problemlos:

main() {

Klasse objekt; // bezeichner gültig, trotz exception

objekt.test(); // keine Möglichkeit die Gültigkeit zu prüfen -> Absturz

}

Allein deswegen würd ich das Ding fertig erstellen lassen - oder mich an einer anderen Stelle darum kümmern. Wie gesagt, lieber einmal zu oft auf .IsValid() prüfen, einen zustand den ich im Konstruktor setzen könnte, anstatt auf gut Glück etwas zu tun.

Im Falle

Klasse *Objekt = NULL;

Objekt = new Klasse(); sieht das anders aus, da kann ich brav NULL prüfen, aber da ich nicht immer auf'm Heap rumhampel und mich auch bei einem $Fremder nicht darauf verlassen will, dass er meine Fehlerbehandlungen korrekt übernimmt, würde ich lieber ein gültiges Objekt erstellen, das versucht die von $Fremder eingebauten Fehler vernünftig zu behandeln. In einer hypothetischen double CBruch::Divide(); Methode eben bspw. zu prüfen n == 0 und einen Ausnahmezustand zurückgeben, o.ä., allerdings einem anderen - soweit irgendwie möglich - nie die möglichkeit einräumen das Programm zu crashen.

Oder eben wie gesagt: Factory her, wie ich meinen Konstruktor da behandel ist gänzlich mir überlassen und ich entscheide was $Fremder in die Hand bekommt.

Bearbeitet von Klischeepunk
Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn ich mich richtig erinner meckert bei Java netterweise auch der Compiler, wenn ich ne Exception nicht behandel, mein Compiler übersetzt folgendes allerdings Problemlos:

main() {

Klasse objekt; // bezeichner gültig, trotz exception (*)

objekt.test(); // keine Möglichkeit die Gültigkeit zu prüfen -> Absturz

}

Ohne, dass ich jetzt die Spezifikation im Kopf habe (und getestet habe), müsste bei (*) wenn die Exception auftritt das Programm terminieren, denn da die Exception nicht gefangen wurde, geht sie an die höchste Instanz, d.h. das Hauptprogramm und das müsste dann terminieren.

siehe terminate - C++ Reference

The terminate handler by default simply calls abort.

Das abort generiert ein SIGABRT und ruft nicht den Destruktor der Objekte auf, d.h. in dem Fall bricht es ab.

unter abort - C++ Reference

Aborts the process with an abnormal program termination.

The function generates the SIGABRT signal, which by default causes the program to terminate returning an unsuccessful termination error code to the host environment.

D.h. das OS übernimmt hier. Heap bleibt meine Sache, aber entsprechende Stackbereiche müssten durch das OS entsprechend bereinigt werden.

Allein deswegen würd ich das Ding fertig erstellen lassen - oder mich an einer anderen Stelle darum kümmern. Wie gesagt, lieber einmal zu oft auf .IsValid() prüfen, einen zustand den ich im Konstruktor setzen könnte, anstatt auf gut Glück etwas zu tun.

Das geht nicht immer. Bei sehr großen Objekten z.B. Matrizen kann ich das nicht mehr machen, wenn ich z.B. eine Matrix elementweise ablege und nun bei jedem Elementzugriff entsprechend prüfen muss, dann geht das unglaublich auf die Performance (bitte mal von 10^6, 10^10 oder 10^12 oder noch mehr Elementen ausgehen).

Objekt = new Klasse(); sieht das anders aus, da kann ich brav NULL prüfen, aber da ich nicht immer auf'm Heap rumhampel und mich auch bei einem $Fremder nicht darauf verlassen will, dass er meine Fehlerbehandlungen korrekt übernimmt, würde ich lieber ein gültiges Objekt erstellen, das versucht die von $Fremder eingebauten Fehler vernünftig zu behandeln.

Nein, das sehe ich gar nicht so. Wenn ich eine Klasse konzipiere, dann hat diese definierte Zustände. Bekannte Fehler kann ich durch das Werfen von Exception entsprechend dem Benutzer mitteilen, d.h. aber, wenn dieser eben kein Fehlerhandling implementiert, ist das nicht Sache meiner Klasse das für ihn zu machen. Theoretisch könnte man ja in den Speicherbereich des Objektes irgendwelche Daten schreiben, d.h. ich müsste bei jedem Aufruf einer Methode prüfen, ob die Daten des Objektes konsistent sind, worunter die Performance leidet. Fehlerhandling ist immer Sache der übergeordneten Struktur.

Bearbeitet von flashpixx
Link zu diesem Kommentar
Auf anderen Seiten teilen

main() {

Klasse objekt; // bezeichner gültig, trotz exception

objekt.test(); // keine Möglichkeit die Gültigkeit zu prüfen -> Absturz

}

Wie flashpixx schon sagte: Wenn hier der Klasse-Konstruktor eine Exception wirft, kommt es nie zum Aufruf von test().

Allein deswegen würd ich das Ding fertig erstellen lassen - oder mich an einer anderen Stelle darum kümmern. Wie gesagt, lieber einmal zu oft auf .IsValid() prüfen, einen zustand den ich im Konstruktor setzen könnte, anstatt auf gut Glück etwas zu tun.
Exceptions sind genau dafür da, damit du deinen Code nicht mehr mit solchen Prüfung zupflastern musst.

Im Falle

Klasse *Objekt = NULL;

Objekt = new Klasse(); sieht das anders aus, da kann ich brav NULL prüfen,

new gibt niemals NULL zurück. new wirft eine Exception, wenn nicht genug Speicher da ist.

Das ist C-Style, genau wie die Nullinitialisierung mit nachfolgender Neuzuweisung.

Das ist doch das Schöne an Exceptions: Wenn der Konstruktor ordentlich implementiert ist, also eine Exception wirft, wenn was nicht klappt, dann kannst du, wenn das Programm nach diesem new weiterläuft, davon ausgehen, dass alles geklappt hat. Es war genug Speicher da, und das Objekt konnte fehlerfrei erstellt werden. Du brauchst an dieser Stelle dann keine Gültigkeitsprüfung.

Ein sauber aufgezogenes C++-Programm sieht immer ein wenig aus wie "Schönwetterprogrammierung". Man geht davon aus, dass alles klappt. Wenn was nicht klappt, fliegt eine Exception, die an geeigneter Stelle behandelt wird. Exceptions bieten die Möglichkeit, die Fehlerbehandlung von der Programmlogik zu trennen. Ansonsten gibt das einen heillosen Mischmasch aus Code, der etwas tut, und Code, der nur dazu da ist, zu prüfen, ob alles geklappt hat.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...