@Title:
<klugscheissmodus>
Destruktor, nicht Dekonstruktor.
Du sagst doch auch nicht etwas ist dekonstruktiv, sondern etwas ist destruktiv.
</klugscheissmodus>
@Code:
...
:kotz:
Musterprüfung für eine Klausur
Oh Junge, ich würd die Hochschule/Uni/whatever wechseln.
Es gibt sehr sehr selten einen triftigen Grund einen Destruktor manuell aufzurufen.
Und hier ist das sicherlich nicht der fall.
maria, peter, franz, luisa, mary, luise, p sind keine dynamisch angelegten Instanzen, auf diese rufst du also schonmal keinen Destruktor auf.
Das wird automatisch für dich gemacht. Nur bei dynamisch angelegtem Speicher (new keyword) wird der Destruktor aufgerufen, und dort mal von sehr exotischen Fällen abgesehen nur über das delete keyword.
Dies soll scheinbar eine liste der Personen sein, aber es werden hier 7 neue Instanzen der Klasse Person erzeugt.
Diesen wird dann später lediglich der Wert zugewiesen der in den vorher angelegten Instanzen gesetzt wurde.
Diese liste ist nun im dynamischen speicher, aber hier löscht man die einträge nicht einzeln via delete freunde
; sondern alle zusammen mit delete[] freunde;
Ich gehe mal stark davon aus, dass der code so gemeint war:
Code: Alles auswählen
#include <iostream>
using namespace std;
int strlen1(const char *str) { // liefert die Laenge von str
if (str == 0) return 0;
int i = 0;
for (; str[i]; ++i);
return i;
}
void strcpy1(const char *src, char *dest) { // kopiert Inhalt von src nach dest
if (src == 0 || dest == 0) return;
int i = 0;
for (; src[i]; ++i) dest[i] = src[i];
dest[i] = '\0';
}
class Person {
char *name;
public:
Person(const char *str = "Susi") {
name = new char[strlen1(str) + 1];
strcpy1(str, name);
}
Person(const Person &p) {
name = new char[strlen1(p.name) + 1];
strcpy1(p.name, name);
}
~Person() {
if (name) delete[] name;
}
void change() {
name[4] = 'e';
}
ostream & print(ostream & o) const {
o << name;
return o;
}
};
int main() {
Person *maria = new Person("Maria"), *peter = new Person("Peter"), *franz = new Person("Franz"), *luisa = new Person("Luisa");
Person *mary = new Person(*maria);
Person *luise = new Person();
Person *p = new Person(*luise);
Person **freunde = new Person *[7];
freunde[0] = maria;
freunde[1] = peter;
freunde[2] = franz;
freunde[3] = luisa;
freunde[4] = mary;
freunde[5] = luise;
freunde[6] = p;
freunde[5] = luisa;
freunde[3]->change();
freunde[4]->change();
for (int i = 0; i < 7; ++i) {
freunde[i]->print(cout);
cout << endl;
}
for (int i = 0; i < 7; ++i)
delete freunde[i];
delete[] freunde;
_getchar_nolock();
return 0;
}
Aber auch das ist noch falsch, denn hier könnte man einen Eintrag doppelt löschen.
Und wenn du einen Array nimmst in dem eine Instanz mehrfach vorkommen kann bedeutet auch dass die Instanz eventuell gar nicht drin vorkommt. Bam! => Memory Leak.
Hier gibt es drei Mögliche Lösungen:
1. Smart Pointer
2. Halte dir eine Liste der (eindeutigen) Instanzen.
3. Jede Instanz für sich deleten.
Auf gar keinen Fall einen Destruktor mehrfach aufrufen, absolutes No-Go.
Und schon gar nicht auf Instanzen die nicht dynamisch angelegt wurden.
Sollte es einfach nur um eine ausgabe einer Freundesliste gegangen sein, so wäre es auch so gegangen:
Code: Alles auswählen
#include <iostream>
using namespace std;
int strlen1(const char *str) { // liefert die Laenge von str
...
}
void strcpy1(const char *src, char *dest) { // kopiert Inhalt von src nach dest
...
}
class Person {
...
};
int main() {
Person maria("Maria"), peter("Peter"), franz("Franz"), luisa("Luisa");
Person mary(maria);
Person luise;
Person p(luise);
Person **freunde = new Person *[7];
freunde[0] = &maria;
freunde[1] = &peter;
freunde[2] = &franz;
freunde[3] = &luisa;
freunde[4] = &mary;
freunde[5] = &luise;
freunde[6] = &p;
freunde[5] = &luisa;
freunde[3]->change();
freunde[4]->change();
for (int i = 0; i < 7; ++i) {
freunde[i]->print(cout);
cout << endl;
}
delete[] freunde; //löscht lediglich den array, nicht die personen.
_getchar_nolock();
return 0;
// Nach beendung von main() werden die personen automatisch gelöscht, da nicht über new angelegt.
}