Seite 1 von 1

[gelöst] Qt Destruktoren

Verfasst: 13. September 2007 00:45
von QNoob
Moin,

Sorry schon mal, falls die Frage zu dumm ist, aber ich konnte dazu nichts sinnvolles finden und bin noch ziemlich unerfahren, was C++ angeht.

Ich habe gelesen, dass children Objekte automatisch vom parent gelöscht werden, wenn dieser aufhört zu existieren. Wenn man jetzt den Destruktor einer Qt-Klasse überlädt, geht dann die Funktionalität verloren, dass die children automatisch gelöscht werden? :?

Verfasst: 13. September 2007 07:30
von macman
Wenn Du eine Funktion erweiterst, dann muss die Funktion der Basisklasse mit aufgerufen werden. Wenn Du sie ersetzt, dann lässt man das eben.

Verfasst: 13. September 2007 07:37
von Christian81
@macman: Es überschreibt nicht eine Funktion sondern einen dtor/ctor!

Es werden immer aller ctors der Reihe nach aufgerufen (von oben nach unten) und am Ende auch alle dtors (auch von oben nach unten). Also nichts mit überschreiben.

Verfasst: 13. September 2007 08:01
von macman
Stimmt, nicht bedacht. Der Konstruktor der Basisklasse wird ja auch aufgerufen, ohne das man das explizit machen muss. Warum sollte das dann beim Destruktor nicht auch der Fall sein.

Verfasst: 13. September 2007 09:42
von Deever
macman hat geschrieben:Der Konstruktor der Basisklasse wird ja auch aufgerufen, ohne das man das explizit machen muss.
Falsch. Oder zumindest misverständlich.

Gruß,
/dev

Verfasst: 13. September 2007 10:14
von Volker
Also meiner Meinung nach muss man den Konstruktor der Basisklasse explizit aufrufen, den Destructor jedoch nicht. Allerdings sollte man den Destructor in der Oberklasse deshalb immer virtual machen, da wenn das Objekt auf Basis einer Variablen vom Typ der Oberklasse gelöscht wird, der Unterklassendestruktor nicht aufgerufen wird.
Und demnach wird soweit ich weiß auch der Destruktor von unten nach oben und nicht von oben nach unten aufgerufen.

Verfasst: 13. September 2007 11:00
von Christian81
Oj man - so viel Unkenntnis in einem Programmiererforum :(
Also meiner Meinung nach muss man den Konstruktor der Basisklasse explizit aufrufen
Falsch - der Compiler ruft den default ctor auf wenn man nichts angibt.
Und demnach wird soweit ich weiß auch der Destruktor von unten nach oben und nicht von oben nach unten aufgerufen.
Na dann viel Spass... überleg dir mal wie das gehen soll.

Verfasst: 13. September 2007 11:26
von Volker
Also a) ja der Oberklassen Konstruktor wird standardmäßig aufgerufen, war mir neu, aber gut zu wissen. Das gilt allerdings auch nur dann, wenn ein Default Konstruktor ohne Parameter vorhanden ist.

aber b) in folgendem Beispiel wird erst der Unterklassen Destruktor aufgerufen und dann der Oberklassen Destruktor!

Code: Alles auswählen

#ifndef UNTERKLASSE_H_
#define UNTERKLASSE_H_

#include "Oberklasse.h"


class Unterklasse : public Oberklasse
{
public:
	Unterklasse() {std::cout << "Unterklassen Constructor" << std::endl;}
	~Unterklasse() {std::cout << "Unterklassen Destructor" << std::endl;}

};

#endif

Code: Alles auswählen

#ifndef OBERKLASSE_H_
#define OBERKLASSE_H_

#include <iostream>

class Oberklasse
{
public:
	Oberklasse() { std::cout << "Oberklassen Constructor" << std::endl; }
	virtual ~Oberklasse() { std::cout << "Oberklassen Destructor " << std::endl; }


};
#endif

Code: Alles auswählen

#include "Oberklasse.h"
#include "Unterklasse.h"

int main(int argc, char** argv)
{
	Unterklasse* klasse = new Unterklasse();
	delete klasse;
}
Und wie ich bereits geschreiben habe, wenn man die Variable klasse vom Typ Oberklasse macht und den Destructor von Oberklasse nicht virtual, dann wird der Destructor der Unterklasse nicht aufgerufen
Und demnach wird soweit ich weiß auch der Destruktor von unten nach oben und nicht von oben nach unten aufgerufen.
Na dann viel Spass... überleg dir mal wie das gehen soll.
Hab ich mir überlegt! Und bin dabei zu folgendem Schluss gekommen: Angenommen im Oberklassen Destruktor wird etwas gelöscht, auf das der Unterklassen Destruktor noch zugreift, dann würde das in deiner Variante zu einem Crash führen... wäre also nicht sinnvoll oder?

Verfasst: 13. September 2007 11:33
von Christian81
Ich glaube mein oben ist dein unten :-D

Ich sehe es als Stack:

class a : public b

a -> oben
b -> unten

das mit dem virtual ist so korrekt. Es wird dann erst in der vtable geschaut und mit dem obersten (nach meiner Leseart) dtor angefangen

Verfasst: 13. September 2007 11:34
von QNoob
Ok, danke für die Antworten. :)

Es ist also so, dass dtors nie "überschrieben" werden, sondern jeder dtor ruft auch automatisch den dtor der Basisklasse auf. Deshalb gibt es dann auch keine Probleme und sobald man virtuelle Funktionen in seiner Klasse hat, muss auch der dtor virtuell sein.

Habe ich das so richtig verstanden?

Verfasst: 13. September 2007 11:55
von Christian81
Ja.
Ich würde allerdings den dtor immer virtual machen.

Code: Alles auswählen

class a
{
public:
 ~a();
}

class b : publicc a
{
public:
 ~b();
}


a *ptrA= new b();
delete ptrA;
Da sonst im obigen Beispiel ~b nicht aufgerufen wird.

Verfasst: 13. September 2007 12:06
von Volker
Christian81 hat geschrieben:Ich glaube mein oben ist dein unten :-D
Dann ist aber dein vorheriger Kommentar widersprüchlich:
Es werden immer aller ctors der Reihe nach aufgerufen (von oben nach unten) und am Ende auch alle dtors (auch von oben nach unten).
Da ich das so verstehe, dass die Reihenfolge bei beiden gleich wäre. Ist sie aber gerade nicht!

Verfasst: 13. September 2007 12:13
von Christian81
Ok, Du hast recht - es ist falsch ausgedrückt. Der 'Body' des ctors wird natürlich erst ausgeführt wenn der ctor der Basisklasse ausgeführt wurde. D.h. er geht erst nach unten und dann wieder nach oben.

Verfasst: 17. September 2007 10:48
von RHBaum
Ich würde allerdings den dtor immer virtual machen.
Was einem wenn man ableitet eigentlich gar nix hilft :-)

Leitest du von ner klasse ab, die nen virtuellen Dtor hat, wird dein Dtor automatisch auch virtuell.
Ich geb Dir aber recht, man sollte das virtual in dem Falle auch dazuschreiben, auch wenns nix mehr bewirkt.

Leitest du von einer klasse ab, die keinen virtuellen Dtor hat, kannst du deinen DTor virtuell machen, die vtable wird dann an deiner klasse angelegt. deleted aber jemand ueber den basiszeiger -> dein Dtor wird nicht aufgerufen -> naja, memleaks und so zeugs.

Wenn du ableitest wird also dein dtor immer virtual sein, oder du leitest von ner klasse ab, die nicht fuers ableiten "gedacht" ist.

Ciao ...