я нахожу Правило нуля как также упоминалось на Питер Соммерладс Слайды (с.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
, Но мой вопрос звучит так: нужно ли вообще объявлять (виртуальные) деструкторы?
На самом деле это базовый деструктор, который должен быть объявлен виртуальным, и он автоматически виртуален в производных классах:
struct Base {
virtual void drawYourself();
virtual ~Base() = default;
};
struct Derived : public Base {
virtual void drawYourself();
};
Но кроме этого, правило нуля все еще выполняется.
Если вы делаете это так, как вы это сделали, или если вы пропустите virtual
деструктор, вы просто получаете неопределенное поведение, когда delete
получение производного объекта через базовый указатель.
Других решений пока нет …