Korrekte Nutzung von Konstruktor, Destruktor
-
Hallo zusammen.
Da C++ Operator-Überladung erlaubt, möchte ich mit meinen Klassen "rechnen" können, wie mit einfachen Zahlen. Ein mathematischer Bruch wäre ein Beispiel für eine solche Klasse. In diesem Zusammenhang bekomme ich jedoch Probleme mit dem Erzeugen und Löschen von Objekten.
Ich erwarte, dass bei jedem Objekt genau einmal der Destruktor aufgerufen wird, und es danach nicht mehr benutzt wird.Nun habe ich eine Klasse "Zahl" erstellt: Ich habe den operator+ überladen, wirklich gerechnet wird aber in diesem Beispiel nichts. Es geht hier nur um das Erzeugen und Löschen der Objekte.
// zahl.cpp #include "zahl.h" #include <iostream> using namespace std; unsigned int Zahl::nextId=1; Zahl::Zahl() { id = nextId++; cout << "Zahl Nr. " << id << " wurde erzeugt." << endl; } Zahl::Zahl(Zahl &a) { id = nextId++; cout << "Zahl Nr. " << a.id << " wurde zu Nr. " << id << "kopiert." << endl; } Zahl::~Zahl() { cout << "Zahl Nr. " << id << " wurde gelöscht." << endl; } void Zahl::ausgeben() { cout << "Dies ist Zahl Nr. " << id << endl; } Zahl Zahl::operator+(const Zahl &a) { cout << "Addiere Zahlen Nr. " << id << " und " << a.id << endl; Zahl neu; return neu; }// zahl.h #ifndef Zahl_H #define Zahl_H class Zahl { public: Zahl(); Zahl(Zahl &a); ~Zahl(); void ausgeben(); Zahl operator+(const Zahl &a); private: static unsigned int nextId; unsigned int id; }; #endif// test-zahl.cpp #include <iostream> #include "zahl.h" using namespace std; int main() { Zahl summe; Zahl summand; for (int i=0; i<2; i++) { summe = summe + summand; } summe.ausgeben(); return 0; }Die Klasse "Zahl" teilt mir nun mit, wann Objekte erzeugt, benutzt und gelöscht werden. Hier meine Ausgabe:
Zahl Nr. 1 wurde erzeugt. Zahl Nr. 2 wurde erzeugt. Addiere Zahlen Nr. 1 und 2 Zahl Nr. 3 wurde erzeugt. Zahl Nr. 3 wurde gelöscht. Addiere Zahlen Nr. 3 und 2 Zahl Nr. 4 wurde erzeugt. Zahl Nr. 4 wurde gelöscht. Dies ist Zahl Nr. 4 Zahl Nr. 2 wurde gelöscht. Zahl Nr. 4 wurde gelöscht.- Zahl Nr. 1 wird nie gelöscht.
- Zahl Nr. 3 wird nach dem Löschen noch einmal benutzt.
- Zahl Nr. 4 wird doppelt gelöscht (und dazwischen noch ausgegeben).Wie kann man dieses Beispiel verändern, damit diese Probleme nicht mehr auftreten?
Ich könnte natürlich auch Zeiger verwenden und über new/delete arbeiten. Aber ist das die einzige Lösung? Oder gibt es auch ohne Zeiger eine saubere Möglichkeit?
-
Regel der großen Drei beachten. Wenn du meinst, in einer Klasse einen selbstdefinierten Destruktor haben zu müssen, dann brauchst du auch praktisch immer mindestens noch einen selbstdefinierten Kopierkonstruktor und Zuweisungsoperator.
-
Vielen Dank, das Stichwort "Zuweisungsoperator" hat mich weiter gebracht.
Zur Vollständigkeit hier noch meine Lösung:
Ich habe die folgende Methode in "zahl.cpp" ergänzt:Zahl &Zahl::operator=(const Zahl &a) { cout << "Zahl Nr. " << id << " wird gleich überschrieben und ist damit gelöscht." << endl; id = nextId++; cout << "Zahl Nr. " << a.id << " wurde zu Nr. " << id << " kopiert." << endl; }Dazu der Prototyp in der Headerdatei "zahl.h":
Zahl &operator=(const Zahl &a);Meine Ausgabe sieht nun so aus:
Zahl Nr. 1 wurde erzeugt. Zahl Nr. 2 wurde erzeugt. Addiere Zahlen Nr. 1 und 2 Zahl Nr. 3 wurde erzeugt. Zahl Nr. 1 wird gleich überschrieben und ist damit gelöscht. Zahl Nr. 3 wurde zu Nr. 4 kopiert. Zahl Nr. 3 wurde gelöscht. Addiere Zahlen Nr. 4 und 2 Zahl Nr. 5 wurde erzeugt. Zahl Nr. 4 wird gleich überschrieben und ist damit gelöscht. Zahl Nr. 5 wurde zu Nr. 6 kopiert. Zahl Nr. 5 wurde gelöscht. Dies ist Zahl Nr. 6 Zahl Nr. 2 wurde gelöscht. Zahl Nr. 6 wurde gelöscht.Damit sind die Probleme gelöst. Auf jedem Objekt wird genau ein Mal der Destruktor aufgerufen und das Objekt danach nicht mehr benutzt.