Vererbungsproblem



  • Hi,

    ich hab ein Problem mit dem Destruktor von abgeleiteten Klassen. Beschreib erstmal die Situation:
    Es gibt eine "Oberklasse" von der alle anderen ableiten.
    Diese Klassen werden dynamisch erzeugt und ihre Zeiger in einer Liste gespeichert, wenn dann aber diese die Objekte anhand des Zeigers gelöscht werden, wird nur der Destruktor der Oberklasse aufgerufen, nicht aber von den "Kinderklassen". Hat vielleicht jemand eine Idee, wie man dies anstellen kann?

    Schreib dazu noch ein vereinfachtes Beispiel:

    class OberKlasse
    {
    public:
       virtual ~OberKlasse(){
          cout << "~OberKlasse wurde aufgerufen\n";
       };
    };
    
    class Kind1 : public OberKlasse
    public:
       virtual ~Kind1(){
          cout << "~Kind1 aufgerufen\n";
       };
    };
    
    class Kind2 : public OberKlasse
    public:
       virtual ~Kind2() {
          cout << "~Kind2 aufgerufen\n";
       };
    };
    
    int main()
    {
       list<OberKlasse*> items;
       OberKlasse * k = NULL;
    
       k = new Kind1;
       items.add(k);
    
       k = new Kind2;
       items.add(k);
    
       // Jetzt alles löschen
       list<OberKlasse*>::iterator iter = items.begin();
       while (iter != items.end()){
          delete *iter;  // < hier wird nur der Destruktor von OberKlasse aufgerufen
          iter ++;
       }
    }
    

    Vieleicht sind hier ein paar Fehler, aber Hauptsache das man versteht was ich meine 😉



  • Das muss so aber funktionieren, tut es bei mir auch (nachdem ich zwei { eingefügt und add durch push_back ersetzt habe):

    ~Kind1 aufgerufen
    ~OberKlasse wurde aufgerufen
    ~Kind2 aufgerufen
    ~OberKlasse wurde aufgerufen

    Davon abgesehen sind rohe Pointer in STL-Containern (die die Objekte wirklich besitzen sollen und nicht nur beobachten) keine sehr sichere Angelegenheit, aber das Thema hatten wir schon in einem anderen Thread.



  • Davon abgesehen sind rohe Pointer in STL-Containern (die die Objekte wirklich besitzen sollen und nicht nur beobachten) keine sehr sichere Angelegenheit...

    Nein, STL-Container sollte ihre Objekte keineswegs immer besitzen. Die polymorphe Verwendung von Objekten, wie bIce sie hier zeigt, ist ein gutes Beispiel dafür, wann das nicht angebracht ist. Oder wie sollte man es sonst machen?!
    Daß der passende Destruktor nicht aufgerufen wird, kann ich allerdings auch nicht nachvollziehen. Ist der gezeigte Code wirklich gleich dem verwendeten? Vielleicht ist der Destruktor von OberKlasse im Original nicht virtuell?

    Stefan.



  • DStefan schrieb:

    Vielleicht ist der Destruktor von OberKlasse im Original nicht virtuell?

    Danke, er war tatsächlich nicht virtuell, jetzt funktionierts es aber. Den Code oben habe ich aus dem Gedächtnis getippt, da ich nicht an meinem Computer saß. Ich habe ihn auch nicht getestet, weil ich keinen Compiler zur Verfügung hatte.

    operator void schrieb:

    Davon abgesehen sind rohe Pointer in STL-Containern (die die Objekte wirklich besitzen sollen und nicht nur beobachten) keine sehr sichere Angelegenheit, aber das Thema hatten wir schon in einem anderen Thread.

    Mit der STL hatte ich bis vor letzte Woche recht wenig zu tun. Muss damit erstmal etwas Erfahrung sammeln.



  • DStefan schrieb:

    Nein, STL-Container sollte ihre Objekte keineswegs immer besitzen. Die polymorphe Verwendung von Objekten, wie bIce sie hier zeigt, ist ein gutes Beispiel dafür, wann das nicht angebracht ist. Oder wie sollte man es sonst machen?!

    Indem man gar nicht erst versucht, sich selbst um die Freigabe der angezeigerten Objekte zu kümmern, sondern boost::shared_ptr o.Ä. damit beauftragt. Warum man das (meiner Meinung nach) lieber nicht selbst machen sollte, habe ich in irgendeinem anderen Thread etwas ausführlicher beschrieben...aber frag mich nicht, in welchem 🙂 Genauso sicher und ohne den Referenzzählungsoverhead wäre es nur möglich, wenn der Move-Proposal in den Standard aufgenommen würde *träum*


Anmelden zum Antworten