Når skal man bruke virtuelle ødeleggere?

Jeg har en solid forståelse av det meste av OO-teori, men den ene tingen som forvirrer meg mye er virtuelle destruktorer.

Jeg trodde at destruktoren alltid blir kalt uansett hva og for hvert objekt i kjeden.

Når er det meningen at du skal gjøre dem virtuelle og hvorfor?

Løsning

Virtuelle destruktorer er nyttige når du potensielt kan slette en forekomst av en avledet klasse gjennom en peker til basisklassen:

class Base 
{
    // some virtual methods
};

class Derived : public Base
{
    ~Derived()
    {
        // Do some important cleanup
    }
};

Her vil du legge merke til at jeg ikke erklærte Base's destructor for å være virtuell. Nå, la oss ta en titt på følgende utdrag:

Base *b = new Derived();
// use b
delete b; // Here's the problem!

Siden Base's destructor ikke er virtuell og b er en Base* som peker til et Avledet objekt, har delete b udefinert oppførsel:

[I delete b], hvis den statiske typen til objektet som skal slettes, er objektet som skal slettes, er forskjellig fra dets dynamiske type, skal den statiske typen være en basisklasse av den dynamiske typen til objektet som skal slettes og slettes, og den statiske typen skal ha en virtuell destruktor eller den oppførsel er udefinert.

I de fleste implementasjoner vil kallet til destruktoren løses som en hvilken som helst ikke-virtuell kode, noe som betyr at destruktoren til basisklassen vil bli kalt, men ikke den til den avledede klassen, noe som resulterer i en ressurslekkasje.

For å oppsummere, gjør alltid baseklasser; destruktorer virtuelle når de er ment å bli manipulert polymorfisk.

Hvis du vil forhindre sletting av en forekomst gjennom en baseklassepeker, kan du gjøre baseklassens destruktor beskyttet og ikke-virtuell; ved å gjøre det, vil kompilatoren ikke la deg kalle delete på en baseklassepeker.

Du kan lære mer om virtualitet og virtual base class destructor i denne artikkelen fra Herb Sutter.

Kommentarer (10)

Deklarer destruktorer virtuelle i polymorfe basisklasser. Dette er punkt 7 i Scott Meyers' Effektiv C++. Meyers fortsetter med å oppsummere at hvis en klasse har en hvilken som helst virtuell funksjon, bør den ha en virtuell destruktor, og at klasser som ikke er designet for å være basisklasser eller ikke er designet for å brukes polymorfisk, bør ikke erklære virtuelle destruktorer.

Kommentarer (7)

Gjør destruktoren virtuell når klassen din er polymorf.

Kommentarer (0)