Sobes.tech
Junior — Middle

Milyen következmények léphetnek fel, ha egy virtuális függvényt hívunk egy objektum destruktorán belül?

sobes.tech MI

Válasz az MI-től

Amikor egy virtuális függvényt hívunk egy C++-ban lévő objektum destruktorán belül, akkor a hívás a destrukció során az aktuális típusnak megfelelő függvényverziót fogja eredményezni, nem a származtatott osztályét. Ez azért van, mert a destruktor futtatásakor az objektum már "szűkült" az alap osztályra, és a virtuális hívások mechanizmusa nem veszi figyelembe a származtatott osztályokat.

Következmények:

  • Ha a virtuális függvényt a származtatott osztályban felülírták, akkor az alap osztály destruktorán belüli hívás nem fogja ezt a felülírt verziót meghívni, hanem az alap verziót.
  • Ez váratlan viselkedéshez vagy hibákhoz vezethet, ha a függvény a származtatott osztály állapotától függ, amely már meg lett semmisítve.

Példa:

#include <iostream>

struct Base {
    virtual ~Base() {
        foo(); // virtuális függvény hívása
    }
    virtual void foo() { std::cout << "Base::foo" << std::endl; }
};

struct Derived : Base {
    ~Derived() override {
        std::cout << "Derived destruktor" << std::endl;
    }
    void foo() override { std::cout << "Derived::foo" << std::endl; }
};

int main() {
    Base* obj = new Derived();
    delete obj; // meghívja a Base::~Base(), amelyben a foo() a Base::foo-t hívja
}

A kimenet:

Derived destruktor
Base::foo

Ezért a virtuális függvényhívás a destruktorban nem hívja meg a származtatott osztály felülírt verzióját.