Seite 1 von 1
2 Voneinander abhängige Klassen deklarieren...
Verfasst: 21. Dezember 2008 11:39
von Gapa
Hallo,
mein Problem ist eigentlich schon mit der Überschrift geschildert worden.
Ich möchte 2 Klassen in einer Header-datei deklarieren, welche jeweils eine Variable von der anderen Klasse enthalten.
Jedoch ist immer bei der zuerst deklarierten Klasse das Problem, dass es die Variable vom Typ der anderen Klasse ja noch nicht kennt! Habt ihr verstanden was ich meine??
Wie stelle ich es nun an, dass beide Klassen deklariert werden können, sodass jede Klasse eine Variable vom Typ der anderen Klasse enthält??
Viele Grüße
Gapa
Verfasst: 21. Dezember 2008 12:59
von franzf
Die einfachste Lösung wäre, wenn du einen Pointer auf ein Objekt der jeweils anderen Klasse anlegst:
Code: Alles auswählen
class A;
class B;
class A
{
protected:
B* b;
};
class B
{
protected:
A* a;
};
int main(int, char**)
{
A a;
return 0;
}
So kommst du mit der Forward-declaration von A und B ganz gut um die Runden.
Musst halt im Destruktor deine member selbst zerstören.
Grüße
Franz
Verfasst: 22. Dezember 2008 01:10
von The User
Den Pointer solltest du nicht zerstören, weil er ja auf ein normales (nicht dynamisch) erstelltes Objekt zeigt.
Verfasst: 22. Dezember 2008 12:05
von franzf
The User hat geschrieben:Den Pointer solltest du nicht zerstören, weil er ja auf ein normales (nicht dynamisch) erstelltes Objekt zeigt.
Das kann man so nicht sagen

Vorher hatte er keinen Pointer. Den Pointer nehm ich nur, dass es mit der Forward-Declaration klappt.
Ich nehme nicht an, dass er nun Methoden bereitstellen wird, mit denen man ein an anderer Stelle erstelltes Objekt dem Pointer zuweisen kann. Demnach wird es relativ sicher sein, den Pointer zu zerstören.
Ansonsten sollte natürlich die "oberste Klasse", welche mit genau diesem Pointer hantiert, das Erstellen und zerstären übernehmen.
Wobei auch hier aufgepasst werden muss, dass man nicht am Ende einen Pointer löscht, welcher noch in dieser (oder einer anderen Klasse) verwendet wird. Kann böse enden, also immer schon auf "!=NULL" prüfen.
Verfasst: 22. Dezember 2008 13:25
von pfid
The User hat geschrieben:Den Pointer solltest du nicht zerstören, weil er ja auf ein normales (nicht dynamisch) erstelltes Objekt zeigt.
Die zeigen eig. nur irgendwo in den Speicher.
franzf hat geschrieben:Kann böse enden, also immer schon auf "!=NULL" prüfen.
Löschen wenn != 0, oder nicht löschen wenn != 0? Ersteres löst das Problem dass du ansprichst nicht, letzteres macht nichts böses =) Löst aber auch kein Problem, da du das Objekt dann ja eh nicht löscht

Verfasst: 22. Dezember 2008 13:33
von franzf
pfid hat geschrieben:franzf hat geschrieben:Kann böse enden, also immer schon auf "!=NULL" prüfen.
Löschen wenn != 0, oder nicht löschen wenn != 0?
Ich entscheide mich für -- 3

Ich meinte natürlich drauf zugreifen.
Wenn du einen Pointer als Member hast, der sich dynamisch ändert, musst du irgendwo prüfen ob der i.O. ist, denn sonst gibts nen segfault.
Setzt natürlich voraus, dass ein pointer, wenn man ihn mit delete jagt und erlegt, auch schön auf 0 setzt. Denn delete zerstört nur das Objekt hinter dem Pointer, der Pointer speichert aber nur die Adresse auf dieses Objekt, und diese ist nach einem delete noch immer gespeichert.
Verfasst: 22. Dezember 2008 13:34
von solarix
Das Ganze ist eigentlich Blödsinn, weil 99% dieser Fälle Designfehler sind. Zyklomatische Abhängikeiten sind -wie diese Diskussion zeigt- im Design unklar und sollten/können (fast) immer vermieden werden. Wenn ein "Parent" eins oder mehrere "Childs" besitzt (also die Instanz erstellt und den Pointer darauf speichert) kann das Child in Qt (falls tatsächlich unbedingt erforderlich) problemlos über Signals Daten und Events an den Parent senden, ohne diesen zu kennen.
Fazit: obiges Problem sollte unbedingt anderst gelöst werden.
Falls (aus Faulheit) keine andere Lösung in Betracht gezogen wird, sollten noch folgende Irrtümer behandelt werden:
franzf hat geschrieben:
Das kann man so nicht sagen
Doch, im Falle deines (!) Beispieles kann man das 100% ganz genau so sagen. In deinem Beispiel liegt das Objekt auf dem Stack, nicht auf dem Heap... also _kein_ Löschen im Destruktor.
franzf hat geschrieben:
Demnach wird es relativ sicher sein, den Pointer zu zerstören.
Es darf kein "relativ" sicher geben... es muss 100% klar sein, wer welche Instanz verwaltet und daher am Ende löschen darf/muss. Sollte dies in einem seltenen Fall anderst sein (zwei oder mehr Instanzen besitzen Pointer auf Objekt), kann das mit "Reference-Counting" (Smartpointer) gelöst werden oder in dem z.B. (bei QObjects) auf das Signal "destroyed()" reagiert wird (alle anderen "Besitzer" setzen Pointer auf NULL).
franzf hat geschrieben:
Wobei auch hier aufgepasst werden muss, dass man nicht am Ende einen Pointer löscht, welcher noch in dieser (oder einer anderen Klasse) verwendet wird. Kann böse enden, also immer schon auf "!=NULL" prüfen.
Aber genau im 2. von dir geschildertem Fall (Verwendung in zweiter Klasse) bringt dein "Tipp" nichts, weil der Zeiger in eben dieser zweiten Klasse _nicht_ NULL ist... (der Zeiger der ersten (löschenden) Klasse übrigens auch nicht, wenn er nach dem Löschen nicht explizit auf NULL gesetzt wurde)