C++ Wie Dekonstruktor einsetzen?
*Markus
- sonstiges
1 Fabian Transchel0 *Markus
0 Der Martin0 *Markus
0 Marko0 Hopsel
Hallo,
Bei der oo Programmierung in C++ ist mir die Verwendung des Dekonstruktors nicht ganz klar. In den Beispielen meines mir zur Verfügung stehenden Buches steht im Dekonstruktor nichts wirklich sinnvolles drin, z.B.
sub::~sub() {
cout << "\n S >> ... Im Destruktor der Subklasse";
}
So weit ich weiß, soll der Dekonstruktor die selbe Aufgabe des Garbage Collectors in Java haben, also die unreferenzierten Instanzen aus dem Speicher zu entfernen. Nur ist mir hierbei nicht klar, ob die Speicherfreigabe "automatisch" vom Programm verwendet wird, ermöglicht durch die bloße Tatsache des vorhandenen Dekonstruktors, oder ob ich explizit noch irgendwelchen Code schreiben muss.
Falls es automatisch geschieht, wie ich meine, frage ich mich, was denn nun in der obrigen Funktion eigentlich drinstehen muss?
Markus.
Hallo *Markus,
Bei der oo Programmierung in C++ ist mir die Verwendung des Dekonstruktors nicht ganz klar. In den Beispielen meines mir zur Verfügung stehenden Buches steht im Dekonstruktor nichchaftents wirklich sinnvolles drin, z.B.
Du hast das schon ganz richtig beschrieben, normalerweise wird der Dekonstruktor dazu verwendet, aufzuräumen, wenn das Objekt nicht mehr benötigt wird. Das kann zum Beispiel bedeuten, dass er den Speicher zurückgibt, aber auch gehaltvollere Sachen umfassen, beispielsweise den Datenabgleich mit einer Datenbank.
Stell dir vor, du hast ein Objekt, dessen Eigenschaften nach seiner Dekonstruktion in einer Datenbank erhalten werden sollen. Natürlich kannst du jedesmal, wenn eine Eigenschaft zur Laufzeit geändert wird, das auch an die DB melden, aber sobald das *mehrmals* zur Laufzeit passiert, und du keine Echtzeitumgebung hast, ist das natürlich ineffizient, weil die Daten unnötigerweise zu oft an die DB geschickt werden, es reicht also aus, dass der Dekonstruktor _einmal_, nämlich dann, wenn es keine weiteren Änderungen geben wird (weil das Object vernichtet wird), diese an die Datenbank zurückgibt.
Grüße aus Barsinghausen,
Fabian
Hallo,
Stell dir vor, du hast ein Objekt, dessen Eigenschaften nach seiner Dekonstruktion in einer Datenbank erhalten werden sollen. [...]
Das klingt eigentlich plausibel. Also habe ich das jetzt richtig verstanden, dass der Dekonstruktor, wenn auch nichts in der Funktion angegeben wurde, er _mindestens_ den Speicher freigibt, und ich mit zusätzlichen Angaben in dieser Funktion eben solche Aufgaben, wie von dir beschrieben, lösen könnte?
Markus.
Hallo *Markus,
Stell dir vor, du hast ein Objekt, dessen Eigenschaften nach seiner Dekonstruktion in einer Datenbank erhalten werden sollen. [...]
Das klingt eigentlich plausibel. Also habe ich das jetzt richtig verstanden, dass der Dekonstruktor, wenn auch nichts in der Funktion angegeben wurde, er _mindestens_ den Speicher freigibt, und ich mit zusätzlichen Angaben in dieser Funktion eben solche Aufgaben, wie von dir beschrieben, lösen könnte?
Jein - nur wenn die Objekte selbst dynamisch Speicher anfordern, dann muss der auch wieder freigegeben werden. Der Speicher der Instanzvariavblen muss nicht freigegeben werden, das passiert automatisch *nachdem* der Dekonstruktor ausgeführt wurde. ("Nachdem" nur im Sinne dessen, dass es hinterher passiert, der Vorgang wird direkt auf den Dekonstruktor folgen.) Alles andere wäre auch sinnfrei, da du im Dekonstruktor noch auf die Instanzvariavblen zugreifen wollen könntest...
Grüße aus Barsinghausen,
Fabian
Hallihallo!
Der Speicher der Instanzvariavblen muss nicht freigegeben werden, das passiert automatisch *nachdem* der Dekonstruktor ausgeführt wurde. ("Nachdem" nur im Sinne dessen, dass es hinterher passiert, der Vorgang wird direkt auf den Dekonstruktor folgen.) Alles andere wäre auch sinnfrei, da du im Dekonstruktor noch auf die Instanzvariavblen zugreifen wollen könntest...
AFAIK müssen jedoch Instanzvariablen, die selber vom Heap alloziert wurden (bsp. Arrays, oder weitere Objekte innerhalb des Objekts) explizit von Hand vernichtet werden, um Speicherlöcher zu vermeiden. Soweit ich weiß, geschieht das nämlich nicht bei der "automatischen Destruktion".
Viele liebe Grüße,
Der Dicki
Hallo,
AFAIK müssen jedoch Instanzvariablen, die selber vom Heap alloziert wurden (bsp. Arrays, oder weitere Objekte innerhalb des Objekts) explizit von Hand vernichtet werden, um Speicherlöcher zu vermeiden. Soweit ich weiß, geschieht das nämlich nicht bei der "automatischen Destruktion".
das gilt aber nur für Arrays oder Objekte, die z.B. im Konstruktor mit dem new-Operator erzeugt wurden. Alles, was in der Klasse direkt (statisch) deklariert ist, wird auch mit dem Destruktor automatisch wieder abgeräumt.
So long,
Martin
Hallihallo!
AFAIK müssen jedoch Instanzvariablen, die selber vom Heap alloziert wurden (bsp. Arrays, oder weitere Objekte innerhalb des Objekts) explizit von Hand vernichtet werden, um Speicherlöcher zu vermeiden. Soweit ich weiß, geschieht das nämlich nicht bei der "automatischen Destruktion".
das gilt aber nur für Arrays oder Objekte, die z.B. im Konstruktor mit dem new-Operator erzeugt wurden. Alles, was in der Klasse direkt (statisch) deklariert ist, wird auch mit dem Destruktor automatisch wieder abgeräumt.
Ja, genau das meinte ich. Auch wenn ich mich anscheinend nicht hundertprozentig ausgedrückt habe.
Viele liebe Grüße,
Der Dicki
Hallo Markus,
Bei der oo Programmierung in C++ ist mir die Verwendung des Dekonstruktors nicht ganz klar.
"Destruktor", nicht "Dekonstruktor".
So weit ich weiß, soll der Dekonstruktor die selbe Aufgabe des Garbage Collectors in Java haben, also die unreferenzierten Instanzen aus dem Speicher zu entfernen.
Hm, wenn das so in einem Progrmmierbuch steht, sollte der Autor seine Formulierung nochmal überdenken.
Packen wir's von der anderen Seite an: Ein Objekt (also eine Instanz einer Klasse) erzeugen wir in C++ mit
obj = new Cls(...);
wobei Cls der Klassenname ist und obj die damit erzeugte Instanz. Dadurch wird ein neues Objekt der entsprechenden Klasse im Speicher angelegt, und der Konstruktor dieser Klasse wird aufgerufen. Der Konstruktor kann durchaus eine leere Funktion sein, wenn das Objekt weiter keine Initialisierung braucht; andernfalls empfiehlt es sich, im Konstruktor die internen Objektvariablen mit sinnvollen Werten zu belegen. Je nach Aufgabe des Objekt ist es sinnvoll, hier weitere Schritte zu unternehmen. Wenn das Objekt beispielsweise mit einer Datei verknüpft ist, die damit bearbeitet werden kann, dann würde ich im Konstruktor auch noch diese Datei öffnen.
Nur ist mir hierbei nicht klar, ob die Speicherfreigabe "automatisch" vom Programm verwendet wird, ermöglicht durch die bloße Tatsache des vorhandenen Dekonstruktors, oder ob ich explizit noch irgendwelchen Code schreiben muss.
"Das kommt drauf an". ;-)
Ein Objekt wird in C++ mit
delete obj;
wieder gelöscht. Dabei wird erst der Destruktor des Objekts aufgerufen (wenn er existiert), und dann der Speicherplatz, den die objekteigenen Variablen belegen, automatisch wieder ordnungsgemäß freigegeben.
Jetzt musst du halt selbst überlegen, ob dein Objekt während seiner "Lebenszeit" etwas gemacht hat, was man beim Beseitigen wieder in Ordnung bringen sollte. Bei meinem obigen Beispiel mit dem Objekt zur Dateimanipulation habe ich im Konstruktor die Datei geöffnet - der logische Schluss wäre also, im Destruktor die Datei wieder ordnungsgemäß zu schließen.
Falls es automatisch geschieht, wie ich meine, frage ich mich, was denn nun in der obrigen Funktion eigentlich drinstehen muss?
Kurz gesagt: All das, was der Konstruktor oder andere Methoden angefangen haben, sollte im Destruktor wieder in Ordnung gebracht werden. Nur das Freigeben des Arbeitsspeichers, den das Objekt belegt, erfolgt automatisch.
Schönes Wochenende noch,
Martin
Hallo,
Bei der oo Programmierung in C++ ist mir die Verwendung des Dekonstruktors nicht ganz klar.
"Destruktor", nicht "Dekonstruktor".
Das hatte ich wohl falsch im Gedächtnis. :)
Hm, wenn das so in einem Progrmmierbuch steht, sollte der Autor seine Formulierung nochmal überdenken.
Das waren eigentlich nur meine eigenen Worte. Außerdem ist es sowieso nur ein C-Buch, und objektorientiertes C++ ist nur im Anhang beschrieben, was aber meiner Meinung hinreichend gut erklärt ist.
Kurz gesagt: All das, was der Konstruktor oder andere Methoden angefangen haben, sollte im Destruktor wieder in Ordnung gebracht werden. Nur das Freigeben des Arbeitsspeichers, den das Objekt belegt, erfolgt automatisch.
Ok, ich bin zwar noch immer nicht ganz sicher, ob ich nun eine leere Funktion deklarieren muss, oder ob ~funktion(); in der Klasse genügt, aber spätestens beim Ausprobieren werde ich merken, ob das so ist. :)
Markus.
Hi Markus,
"Destruktor", nicht "Dekonstruktor".
Das hatte ich wohl falsch im Gedächtnis. :)
macht ja nix. Fabian hat's auch gleich so aufgegriffen, anscheinend ohne dass es ihm aufgefallen ist.
Ok, ich bin zwar noch immer nicht ganz sicher, ob ich nun eine leere Funktion deklarieren muss, oder ob ~funktion(); in der Klasse genügt, aber spätestens beim Ausprobieren werde ich merken, ob das so ist. :)
Soweit ich weiß, muss der Destruktor überhaupt nicht deklariert werden, wenn er sowieso nur eine leere Funktion ist.
Aber da bin ich mir nicht hundertprozentig sicher; ich programmiere im Normalfall reines C, nicht C++.
Ciao,
Martin
PS: Anhand dessen, was ich in den letzten paar Wochen so gelesen habe, schlage ich dir vor, "Strucktur" noch in deine Sig aufzunehmen. ;-)
Hi!
Soweit ich weiß, muss der Destruktor überhaupt nicht deklariert werden, wenn er sowieso nur eine leere Funktion ist.
Aber da bin ich mir nicht hundertprozentig sicher;
Das stimmt. Genauso verhält es sich übrigens auch mit dem Konstruktor; ist keiner angegeben, generiert C++ einen Standardkonstruktor (ohne Parameter).
Hallo,
Das stimmt. Genauso verhält es sich übrigens auch mit dem Konstruktor; ist keiner angegeben, generiert C++ einen Standardkonstruktor (ohne Parameter).
Wenn mich nicht alles täuscht, ist es in Java genauso. Jedenfalls ist jetzt alles klar, danke euch allen.
Markus.
Hallo Der Martin,
"Destruktor", nicht "Dekonstruktor".
Das hatte ich wohl falsch im Gedächtnis. :)macht ja nix. Fabian hat's auch gleich so aufgegriffen, anscheinend ohne dass es ihm aufgefallen ist.
Es ist mir tatsächlich nicht aufgefallen. Es war mir sonnenklar, dass der Destruktor gemeint ist, und weil es mir so klar schien habe ich vergessen, dass das Wort... "ungenau" ist, übrigens ging es mir auch im zweiten Posting so. Es ist ja zum Glück nicht so, dass das Wort eine andere Bedeutung hätte, die verkehrt wäre... ;-)
Grüße aus Barsinghausen,
Fabian
Hallo Markus,
ein ganz praktisches Beispiel. Allen Speicher den Du mit malloc reserviert hast, solltest Du irgendwann mit free wieder freigeben. C++ macht das im Gegensatz zu Java nicht automatisch.
Was Du nicht mit free freigibst wird erst nach der kompletten Beendigung des Programms freigegeben.
Gruss
Marko
Hi *Markus!
Falls es automatisch geschieht, wie ich meine, frage ich mich, was denn nun in der obrigen Funktion eigentlich drinstehen muss?
Ich weiß nicht, ob dir das jetzt klar geworden ist, deswegen möchte ich meinen Senf noch dazugeben:
Du musst den Destruktor gar nicht explizit deklarieren. Das macht der Compiler für dich. [1]
Nur wenn du mit der Auflösung eines Objektes eine bestimmte Aufgabe in Verbindung bringen willst, kannst du den Standart( :-) )destruktor überladen.
Ich habe das einmal benutzt um zu sehen, wann der Destruktor aufgerufen wird. Meistens ist dies aber nicht nötig. ;-)
[1] Ich weiß, das steht schon da...
MfG H☼psel