2011-01-10 10 views
0

Hier ist mein Problem:Abgeleitet destructor vor Basis destructor genannt verursacht Ausgabe

Meine Basisklasse hat einen Konstruktor, der in einem Klassenzeiger nimmt, wenn der Zeiger NULL ist, weiß es zu Beispiel es selbst und es zu halten.

Das Problem ist, im Basisdestruktor muss ich diesen Zeiger mit etwas Privatem der Basis aufheben. Was passiert, wenn ich versuche, einen Aufruf an den Klassenzeiger im Basisdestruktor zu machen, und der abgeleitete es verwaltet, wurde er bereits freigegeben. Das verursacht ein Problem. Was könnte ich tuen?

Dank

Antwort

0

Wenn die Basisklasse schafft eine Instanz für den Zeiger, warum kann es nicht frei es auch? Gibt es etwas, das dich daran hindert, das Freie in den Basisdestruktor zu bringen?

Es ist immer am besten konsistent zu sein, wer was macht, auf einer bestimmten Hierarchieebene - die Aufteilung der gleichen Verantwortung über mehrere Hierarchieebenen wird sicherlich zu solchen Problemen führen. Ganz zu schweigen davon, wenn Sie eine andere Klasse erstellen möchten, die von der Basis erbt, müssen Sie diese Verwaltung auch in der neuen Klasse erneut implementieren und Codeduplikation erstellen.

0

Die Reihenfolge der Konstruktoren und Destruktoren in inheritence entgegengesetzt ist; Der Basiskonstruktor wird vor allen abgeleiteten Konstruktoren aufgerufen. Nach dem Löschen geschieht die Umkehrung - die abgeleitete Klasse wird zuerst gelöscht.

Um Ihr Problem zu lösen, konnte der Basisdestruktor nicht testen, ob seine private Instanz nicht NULL ist?

+0

Ja, ich kann das tun, außer ich muss immer noch eine Funktion dieses spitzen Objekts aufrufen, sonst verursacht es Probleme – jmasterx

0

Aus Ihrer Beschreibung gehe ich hervor, dass manchmal die abgeleitete Klasse verantwortlich für diesen Zeiger ist, und manchmal wird die Basisklasse sein. Die einfachste Lösung, die ich mir vorstellen kann, ist, in Ihrer Basisklasse einen Booleschen Wert hinzuzufügen, mit dem Sie verfolgen können, wem das Objekt gehört. Wenn die Basisklasse den Zeiger initialisiert hat, setzen Sie den Booleschen Wert auf Wahr. Dann kann Ihr Destruktor überprüfen, wem das Objekt gehört und ob es aufgeräumt werden soll.

Eine bessere Lösung wäre die Verwendung von boost: shared_ptr. Dies ist eine Referenzzählungszeigerabstraktion, die Ihr Objekt automatisch bereinigt, wenn seine letzte Referenz den Gültigkeitsbereich verlässt. Bei dieser Abstraktion müssen Sie sich im Allgemeinen keine Gedanken darüber machen, wer Ihren Zeiger freigibt.

0

Die Basisklasse könnte eine protected Memberfunktion implementieren, um die Bereinigung durchzuführen, dann könnte der abgeleitete Destruktor diese Hilfsfunktion aufrufen, bevor die Ressource zerstört wird.

0

Wenn Ihr Konstruktor Speicher reserviert, ist der entsprechende Destruktor für die Freigabe zuständig. Wenn Sie Speicher bedingt zuweisen, müssen Sie ihn bedingt freigeben. Ein boolesches Flag würde Ihnen helfen, festzustellen, ob die Zuweisung stattgefunden hat.

Eine andere Lösung ist eine Referenzzählung. Zum Zeitpunkt der Zuweisung muss die Referenzzählung 1 sein. Wenn eine andere Klasse Interesse an dem Objekt hat, behält sie den Zeiger bei, indem sie die Referenzzählung erhöht. Wenn eine Klasse an dem Objekt nicht mehr interessiert ist, wird die Referenzzahl verringert. Wenn der Zähler 0 erreicht, muss das Objekt gelöscht werden. shared_ptr ist eine Standard-Autozeiger-Implementierung mit C++ - Referenzzählung, die in komplexen gemischten Besitzverhältnissen sehr gut funktioniert.