Ugrás a tartalomhoz

virtual destructor

A Wikiszótárból, a nyitott szótárból


Főnév

virtual destructor (tsz. virtual destructors)

  1. (informatika) A virtuális destruktor (virtual destructor) egy speciális destruktor C++-ban, amely biztosítja, hogy a helyes destruktor hívódjon meg öröklődés esetén. Ha egy osztály nem rendelkezik virtuális destruktorral, akkor polimorfikus használat esetén memóriaszivárgás történhet, mivel a leszármazott osztály destruktora nem hívódik meg.



1. Mi az a destruktor?

Egy destruktor egy olyan speciális függvény egy osztályban, amely akkor fut le, amikor egy objektum megsemmisül (például amikor meghívjuk a delete operátort egy dinamikusan létrehozott objektumra).

Szintaxisa:

class Osztaly {
public:
    ~Osztaly() {
        // Destruktor kódja
    }
};

2. Miért van szükség virtuális destruktorra?

Amikor egy objektumot egy alaposztály mutatóján keresztül törlünk, a helyes destruktor fut le vagy nem attól függően, hogy az alaposztály destruktora virtuális vagy nem.

Ha a destruktor nem virtuális, akkor csak az alaposztály destruktora fut le, és a származtatott osztály erőforrásai nem szabadulnak fel, ami memóriaszivárgáshoz vezethet.



3. Probléma virtuális destruktor nélkül

Példa: Memóriaszivárgás történik, ha nincs virtuális destruktor

#include <iostream>
using namespace std;

class Alap {
public:
    ~Alap() {
        cout << "Alap destruktor" << endl;
    }
};

class Szarmaztatott : public Alap {
public:
    ~Szarmaztatott() {
        cout << "Szarmaztatott destruktor" << endl;
    }
};

int main() {
    Alap* obj = new Szarmaztatott();  // Alap osztály mutatója mutat egy Szarmaztatott objektumra
    delete obj;  // Csak az Alap destruktora hívódik meg!
    return 0;
}

Kimenet:

Alap destruktor

Probléma: - Az Szarmaztatott destruktora nem hívódik meg, így ha tartalmaz dinamikusan foglalt memóriát, az soha nem kerül felszabadításra (memóriaszivárgás!).



4. Megoldás: Virtuális Destruktor

Ha az alaposztály destruktora virtuális, akkor a C++ biztosítja, hogy a leszármazott osztály destruktora is meghívódjon.

Helyes megoldás: Virtuális destruktor használata

#include <iostream>
using namespace std;

class Alap {
public:
    virtual ~Alap() {  // Virtuális destruktor
        cout << "Alap destruktor" << endl;
    }
};

class Szarmaztatott : public Alap {
public:
    ~Szarmaztatott() {
        cout << "Szarmaztatott destruktor" << endl;
    }
};

int main() {
    Alap* obj = new Szarmaztatott();
    delete obj;  // Most mindkét destruktor lefut!
    return 0;
}

Kimenet:

Szarmaztatott destruktor
Alap destruktor

Mi történik itt?

  1. Az Alap destruktora virtuális, így a C++ dinamikus kötést használ.
  2. Először a Szarmaztatott destruktora fut le, ami felszabadítja a Szarmaztatott erőforrásait.
  3. Ezután az Alap destruktora hívódik meg.
  4. Nincs memóriaszivárgás, minden erőforrás felszabadul.



5. Mikor kell virtuális destruktort használni?

Virtuális destruktorra van szükség, ha: ✅ Az osztály öröklődhet más osztályok által.
✅ Az osztály példányait alaposztály mutatóin keresztül is törölhetjük.
✅ Az osztály vagy a leszármazottak dinamikus memóriát használnak (new).

Virtuális destruktorok használatának szabályai

Helyzet Virtuális destruktor szükséges? Miért?
Nincs öröklés ❌ Nem kell Nincs polimorfizmus
Öröklés, de soha nem használunk delete-et az alaposztály mutatóján keresztül ❌ Nem kell Nincs polimorf törlés
Öröklés, és delete-et használunk alaposztály mutatóval ✅ Igen kell Megakadályozza a memóriaszivárgást



6. virtual destruktor és teljesítmény

A virtuális destruktoroknak van egy kis költsége, mert a C++ virtuális táblát (vtable) hoz létre, hogy a helyes destruktort hívja meg futásidőben.

Ez ritkán jelent problémát, de ha egy osztály soha nem lesz örökölt, akkor felesleges a virtual destruktor.



7. override és final virtuális destruktorokkal

C++11-től két új kulcsszóval javíthatjuk a destruktorokat:

override a pontos felüldefiniálásért

class Alap {
public:
    virtual ~Alap() {}
};

class Szarmaztatott : public Alap {
public:
    ~Szarmaztatott() override {}  // A fordító ellenőrzi, hogy tényleg felüldefiniáljuk
};
  • Ha nincs virtual az alaposztályban, a fordító hibát ad.
  • Biztonságosabb, mert segít az elírások ellenőrzésében.

final a további öröklés megakadályozására

class Alap {
public:
    virtual ~Alap() final {}  // Ezt már nem lehet tovább felüldefiniálni
};

class Szarmaztatott : public Alap {
public:
    // ~Szarmaztatott() override {}  // Fordítási hiba! Mert `final`-ként van jelölve
};
  • Ha egy destruktor final-ként van jelölve, nem lehet felüldefiniálni.



8. Összegzés

Fogalom Leírás Példa
Nem virtuális destruktor Csak az alaposztály destruktora fut le ~Alap() {}
Virtuális destruktor A leszármazott osztály destruktora is meghívódik virtual ~Alap() {}
override destruktorral Ellenőrzi, hogy a destruktor valóban felül van-e definiálva ~Szarmaztatott() override {}
final destruktorral Megakadályozza, hogy a destruktort később felüldefiniáljuk virtual ~Alap() final {}



9. Konklúzió

A virtuális destruktor biztosítja, hogy öröklődés esetén az objektumok helyesen törlődjenek, és ne legyen memóriaszivárgás.
Ha egy osztályt polimorf módon használunk, és az lehetőséget biztosít öröklődésre, akkor mindig virtuális destruktort kell használnunk.