Kein Aufruf des Destruktors (Compilerabhängig?)
-
Hier wird der Destruktor nicht aufgerufen.
#include <iostream.h> enum BREED{GOLDEN, CAIRN, DANDIE, SHETLAND, DOBERMAN, LAB}; class Mammal{ public: Mammal(); ~Mammal(); int GetAge() const {return itsAge;} void SetAge(int age) {itsAge=age;} int GetWeight() const {return itsWeight;} void SetWeight(int weight){itsWeight=weight;} void Speak() const {cout << "Saeugetier, gib Laut!\n";} void Sleep() const {cout << "Psst. Ich schlafe.\n";} protected: int itsAge; int itsWeight; }; class Dog : public Mammal { public: Dog(); ~Dog(); BREED GetBreed() const { return itsBreed;} void SetBreed(BREED breed){ itsBreed=breed;} void WagTail(){cout << "Schwanzwedeln...\n";} void BegForFood(){cout << "Um Futter betteln...\n";} protected: BREED itsBreed; }; Mammal::Mammal():itsAge(1),itsWeight(5) { cout << "MammalKonstruktor\n"; } Mammal::~Mammal() { cout << "MammalDestruktor\n"; } Dog::Dog():itsBreed(GOLDEN) { cout << "DogKontruktor\n"; } Dog::~Dog() { cout << "DogDestruktor\n"; } int main(){ Dog difo; difo.Speak(); difo.WagTail(); cout << "Difo (der Hund) ist " << difo.GetAge() << " Jahr(e) alt.\n"; system("pause"); return 0; }
-
1. Destruktoren virtuell machen
2. nimm endl statt "\n", da endl auch die Ausgabe flusht.
-
Mit virtuellen Klassen hab ich mich noch nicht befasst.
Danke trotzdem! Vorallem für endl.
-
1. Destruktoren werden hier korrenkt aufgerufen
2. Verwende iostream ohne .h und den namespace std.
-
Fellhuhn schrieb:
1. Destruktoren virtuell machen
Hat hier nichts mit dem beschriebenen Problem zu tun.
Fellhuhn schrieb:
2. nimm endl statt "\n", da endl auch die Ausgabe flusht.
Wird hier auch nicht helfen. Der Destruktor wird erst nach system("pause") aufgerufen. Da diese Anweisung vermutlich den Zweck hat, das Konsolenfenster offen zu halten, sieht man davon aber nichts mehr.
-
virtual ist hier wichtig. Wenn du eine Klasse erzeugst, von der abgeleitet werden soll, muß deren Destruktor virtual sein, da er sonst in der abgeleiteten Klasse nicht aufgerufen werden kann.
[edit] Ich sollte die Beiträge gründlicher lesen. Sowohl MFK als auch wickelente haben natürlich Recht.
[edit]
-
Braunstein schrieb:
virtual ist hier wichtig. Wenn du eine Klasse erzeugst, von der abgeleitet werden soll, muß deren Destruktor virtual sein, da er sonst in der abgeleiteten Klasse nicht aufgerufen werden kann.
Die Begründung ist falsch. Wenn der Destruktor nicht virtuell ist, geht es in die Hose, wenn ein Objekt der abgeleiteten Klasse über einen Zeiger auf die Basisklasse zerstört wird. Solange hier nur mit automatischen Variablen gearbeitet wird, ist das unnötig.
-
Es geht dabei ja nicht um virtuelle Klassen, sondern darum einfach nur den Destruktor durch ein vorstellen von virtual zu "verbessern". Denn ansonsten wird der Destruktor nicht in allen Fällen korrekt aufgerufen, da kein Eintrag in der vtable vorliegt.
Beispiel:
class Base{ int *a; public: Base(){ a = new int[100]; } ~Base(){ delete[] a; } }; class More : public Base{ int *b; More() : Base(){ b = new int[100]; } ~More(){ delete[] b; } }; //... Base *b = (Base*)new More(); delete b;In dem Fall würde jetzt nur der Base-Destruktor ausgeführt werden, nicht der von More. Und schon hättest du ein Speicherleck. Ein virtualer Destruktor verhindert das.
-
Klingt alles intressant, aber das hat trotzdem nichts mit der Frage des OP zu tun.
Lösung: Die Ausgabe erfolgt nach deinem system-Aufruf, wahrscheinlich siehst du sie nur nicht.
-
Den Destruktor in der Basis Klasse
entweder:
- public und virtuell machen
oder:
- protected und nicht virtuellHerb Sutter oder sonst einer der C++ Gurus.
Gruss Simon
-
Mach ein extra Scope um die Zerstörung zu forcieren.
int main() { { Dog difo; difo.Speak(); difo.WagTail(); cout << "Difo (der Hund) ist " << difo.GetAge() << " Jahr(e) alt.\n"; } system("pause"); return 0; }
-
Fellhuhn schrieb:
Es geht dabei ja nicht um virtuelle Klassen, sondern darum einfach nur den Destruktor durch ein vorstellen von virtual zu "verbessern". Denn ansonsten wird der Destruktor nicht in allen Fällen korrekt aufgerufen, da kein Eintrag in der vtable vorliegt.
und das *muss* nicht immer ein fehler sein. wenn man nicht polymorph arbeitet, dann ist es bestenfalls eine verschlimmbesserung. man glaubt gar nicht, wo virtuelle destruktoren überall überflüssig sein können:
struct Base { ~Base () {} }; struct Derived : Base { ~Derived () {} }; Derived make_some () { return Derived(); } int main () { Base const& base_ref = make_some(); }wunderbar, nicht?
aber generelle aussagen wie "wenn du von einer klasse ableitest, dann musst du den destruktor virtuell machen" treffen es meistens nicht (oft genug vielleicht).
-
Danke, Grundlagen helfen oft weiter (Scopes).
Danke für alle Bemühungen!