Применимо ли "правило нуля" к классам с виртуальными методами?

Я считаю, что правило "ноль", упомянутое на слайдах Питера Соммерлада (стр.32), очень убедительно.

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

struct Base {
    virtual void drawYourself();
    virtual ~Base() {}
};
struct Derived : public Base {
    virtual void drawYourself();
};

Тело деструктора может даже быть пустым (ему нужна только запись в vtbl).

Кажется, я помню, что при использовании иерархии

int main() {
    Base *obj = new Derived{};
    obj->drawYourself(); // virtual call to Derived::drawYourself()
    delete obj; // Derived::~Derived() _must_ be called
}

тогда важно, чтобы delete obj вызывает правильный деструктор. Правильно ли, что если бы я полностью опустил определение деструктора, он не стал бы виртуальным, и поэтому был бы назван неправильный d'or?

struct Base {
    virtual void drawYourself();
    // no virtual destructor!
};

Это приводит меня к моему последнему вопросу:

  • Является ли "правило нуля" также верно для иерархий с виртуальными методами
  • или мне нужно определить виртуальный деструктор в этих случаях?

Редактировать: Как мне напомнили в ответе, моя 1ср версия вопроса имела неправильные предположения. Соответствующий (виртуальный) деструктор находится в Base не Derived, Но мой вопрос звучит так: нужно ли вообще объявлять (виртуальные) деструкторы?

1 ответ

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

struct Base {
    virtual void drawYourself();
    virtual ~Base() = default;
};

struct Derived : public Base {
    virtual void drawYourself();
};

Но кроме этого, правило нуля все еще выполняется.

Если вы делаете это так, как вы это сделали, или если вы пропустите virtual деструктор, вы просто получаете неопределенное поведение, когда deleteполучение производного объекта через базовый указатель.

Другие вопросы по тегам