Подтвердить что ты не робот

Почему деструктор базовых классов должен быть виртуальным?

в С++: зачем деструктор базовых классов быть виртуальным?

4b9b3361

Ответ 1

Лучший вопрос - когда и почему. Ваш вопрос указывает, что вы думаете, что все базовые классы должны иметь виртуальные деструкторы, что не совсем так.

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

A virtual деструктор необходим, если delete объект, динамический тип которого DerivedClass указан указателем с типом BaseClass*. virtual делает компилятор ассоциированной информацией в объекте, позволяя ему выполнять деструктор производного класса. Отсутствие virtual в этом случае вызывает поведение undefined.

Если вам это не нужно, и ваш класс используется только как базовый класс, лучше всего сделать деструктор protected, тем самым предотвращая случайное delete пользователей описанным образом.

Ответ 2

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

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

class derived : public base {
public:
  ~derived() { }  // Inherits the virtual designation
};

int main(void)
{
  base *b = new derived;

  delete b;
}

Выведенный деструктор будет вызываться только в том случае, если базовый деструктор является виртуальным.

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

Ответ 3

В таких ситуациях:

class A
{
    virtual ~A();
};

class B:A
{
    ~B();
};

A *a = new B(); //legal, since it a downcast
delete a; //Unless the destructor is virtual, ~A() is called here instead of ~B().

Ответ 4

Они не должны быть виртуальными, если вы не используете полиморфизм. Если вы используете полиморфизм, они должны быть виртуальными, чтобы гарантировать, что деструкторы унаследованных классов будут вызваны, поэтому унаследованные классы могут очистить их.

Ответ 5

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