← Назад ко всем вопросам

Какие знаешь особенности вызова виртуальной функции из деструктора

1️⃣ Как кратко ответить

Вызов виртуальной функции из деструктора приводит к тому, что будет вызвана версия функции, определенная в текущем классе, а не в производных. Это происходит потому, что во время выполнения деструктора объект уже частично разрушен, и его тип считается типом текущего класса, а не производного.

2️⃣ Подробное объяснение темы

В C++ виртуальные функции позволяют реализовать полиморфизм, что дает возможность вызывать функции производного класса через указатель или ссылку на базовый класс. Однако, при вызове виртуальных функций из деструктора возникают особенности, которые важно учитывать.

Когда деструктор класса вызывается, объект начинает разрушаться, начиная с самого производного класса и заканчивая базовым. В процессе разрушения объект теряет свою связь с производными классами. Это означает, что если в деструкторе базового класса вызывается виртуальная функция, то будет вызвана версия этой функции, определенная в самом базовом классе, а не в производных. Это связано с тем, что на момент вызова деструктора объект уже не является экземпляром производного класса.

Рассмотрим пример:

#include <iostream>
​
class Base {
public:
    virtual ~Base() {
        // Вызов виртуальной функции из деструктора
        // Вызовет Base::show(), а не Derived::show()
        show();
    }
​
    virtual void show() const {
        std::cout << "Base class show function" << std::endl;
    }
};
​
class Derived : public Base {
public:
    ~Derived() override {
        std::cout << "Derived class destructor" << std::endl;
    }
​
    void show() const override {
        std::cout << "Derived class show function" << std::endl;
    }
};
​
int main() {
    Base* obj = new Derived();
    delete obj; // Удаление объекта вызывает деструктор
    return 0;
}
  1. Создание объекта: Base* obj = new Derived(); — создается объект типа Derived, но указатель имеет тип Base*.

  2. Удаление объекта: delete obj; — вызывает деструктор Derived, а затем деструктор Base.

  3. Вызов виртуальной функции: В деструкторе Base вызывается show(). Несмотря на то, что show() переопределена в Derived, будет вызвана версия из Base, потому что на момент вызова деструктора Base объект уже не является экземпляром Derived.

Это поведение важно учитывать при проектировании классов, чтобы избежать неожиданных результатов. Вызов виртуальных функций из деструкторов может привести к тому, что функции производных классов не будут вызваны, что может быть критично, если они выполняют важные операции.

Тема: Классы / ООП / Полиморфизм
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки