Sobes.tech
Junior — Middle

Kādas sekas var rasties, izsaucot virtuālo funkciju objekta destruktorā?

sobes.tech AI

Atbilde no AI

Kad C++ valodā virtuāla funkcija tiek izsaukta objekta destruktora iekšienē, tiek izsaukta funkcijas versija, kas atbilst pašreizējam objekta tipam destrukcijas posmā, nevis mantotās klases versija. Tas ir tāpēc, ka destruktora izpildes laikā objekts jau ir "sašaurināts" līdz pamata klasei, un virtuālo izsaukumu mehānisms neņem vērā mantotās klases.

Sekas:

  • Ja virtuālā funkcija ir pārrakstīta mantotajā klasē, tad zvans destruktora iekšienē neizsauks šo pārrakstīto versiju, bet pamata klases versiju.
  • Tas var novest pie negaidītas uzvedības vai kļūdām, ja funkcija ir atkarīga no mantotās klases stāvokļa, kas jau ir iznīcināts.

Piemērs:

#include <iostream>

struct Base {
    virtual ~Base() {
        foo(); // virtuālas funkcijas izsaukums
    }
    virtual void foo() { std::cout << "Base::foo" << std::endl; }
};

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

int main() {
    Base* obj = new Derived();
    delete obj; // izsauks Base::~Base(), kurā foo() izsauks Base::foo
}

Izvade būs:

Derived destruktors
Base::foo

Tādēļ, izsaucot virtuālo funkciju destruktorā, tā neizsauc pārrakstīto versiju no mantotās klases.