Junior — Middle
Millised tagajärjed võivad tekkida, kui kutsutakse virtuaalset funktsiooni objekti destruktoris?
sobes.tech AI
Vastus AI-lt
Kui C++-s kutsutakse virtuaalset funktsiooni objekti destruktoris, kutsutakse selle funktsiooni versioon, mis vastab objekti praegusele tüübile hävitamise etapis, mitte pärandatud klassi versioon. See on tingitud sellest, et destruktorit käivitades on objekt juba "kitsendatud" baasklassiks, ning virtuaalsete kutsete mehhanism ei arvesta pärandatud klasse.
Tagajärjed:
- Kui virtuaalset funktsiooni on ülekirjutatud pärandatud klassis, siis kutses sisalduv versioon ei kutsu seda ülekirjutatud versiooni, vaid baasversiooni.
- See võib põhjustada ootamatut käitumist või vigu, kui funktsioon sõltub pärandatud klassi seisundist, mis on juba hävitatud.
Näide:
#include <iostream>
struct Base {
virtual ~Base() {
foo(); // virtuaalse funktsiooni kutsumine
}
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; // kutsub Base::~Base(), mille sees foo() kutsub Base::foo
}
Väljund:
Derived destruktor
Base::foo
Seega, virtuaalse funktsiooni kutsumine destruktoris ei kutsu üle kirjutatud versiooni pärandatud klassist.