Виртуальный деструктор: это требуется если не динамично выделенная память?

Нам нужен виртуальный деструктор, если мои классы не выделяют памяти динамично?

например.

class A
{
      private: 
      int a;
      int b;

      public:
      A();
      ~A();
};

class B: public A
{     
      private:
      int c;
      int d;

      public:
      B();
      ~B();
};

В этом случае мы должны отметить деструктор A как виртуальный?

20
задан j0k 1 July 2013 в 14:11
поделиться

5 ответов

Проблема не является ли ваши классы распределить память динамическими. Именно, если пользователь классов выделяет объект B через указатель, а затем удаляет его:

A * a = new B;
delete a;

в этом случае, если нет виртуального деструктора для A, стандарт C ++ говорит, что ваша программа демонстрирует неопределенное поведение. Это не хорошая вещь.

Это поведение указано в разделе 5.3.5 / 3 стандарта (здесь со ссылкой на удалить ):

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

32
ответ дан 29 November 2019 в 23:06
поделиться

деструктор родительского класса всегда автоматически называют, и значение по умолчанию dtor всегда сгенерировано, если нет никакого явного объявленного dtor. В вашем примере ни A, ни B не должны иметь нетривиальный dtor.

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

0
ответ дан 29 November 2019 в 23:06
поделиться

Цель объявления деструктора Как виртуальный должен быть в состоянии вызвать деструкутор полученного класса, когда вы называете удаление на указателе базы типа, который указывает на объект типа получения. Не делает это приведет к неопределенному поведению.

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

0
ответ дан 29 November 2019 в 23:06
поделиться

Память освобождения - это не единственная критическая функция, которую может выполнять деструктор. Он также может использоваться для сброса глобального состояния. Не делать это не будет утечке памяти, но потенциально может вызвать другие проблемы в вашей программе.

Кроме того, даже если ваш деструктор не делает ничего полезного сегодня, он может в какой-то момент в будущем. Там нет настоящей причины, чтобы избежать виртуального деструктора, если у вас наследство, так почему бы не просто добавить его и спать лучше ночью?

4
ответ дан 29 November 2019 в 23:06
поделиться

Цель виртуальный деструктор (т.е. цель изготовления деструктора виртуальный ) содействует содействию полиморфной делеции объектов через Удалить -Экспрессия . Если ваш дизайн не требует полиморфной делеции объектов, вам не нужны виртуальные деструкторы. Ссылаясь на ваш пример, если вам когда-нибудь придется удалить объект типа b через указатель типа A * (полиморфное удаление), вам понадобится виртуальный деструктор в иерархии как A . Вот как это выглядит с официальной точки зрения.

(Примечание, кстати, так как Нил сказал, что то, что важно, это то, как вы создаете / удалите объекты класса, а не как классы управляют своей внутренней памятью.)

Как для хороших практик программирования ... это зависит от вашего намерение и ваш дизайн в конце. Если ваши классы не предназначены для того, чтобы быть полиморфными вообще (без виртуальных методов все большего), то вам не нужны виртуальные деструкторы. Если ваш класс является полиморфным (иметь хотя бы один виртуальный метод), то делая деструктор виртуальный «на всякий случай» может быть очень хорошей идеей, а в этом случае он несет практически нулевую производительность / наказание на память с ним.

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

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

19
ответ дан 29 November 2019 в 23:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: