Можно ли автоматически создать деструктор по умолчанию как виртуальный деструктор? - PullRequest
52 голосов
/ 13 июля 2009

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

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

Ответы [ 7 ]

49 голосов
/ 01 февраля 2014

В C ++ 11 вы можете использовать:

class MyClass
{
  // create a virtual, default destructor
  virtual ~MyClass() = default;
};
45 голосов
/ 13 июля 2009

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

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

9 голосов
/ 13 июля 2009

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

9 голосов
/ 13 июля 2009

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

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

В дополнение к этому.

Цитируя Скотта Мейерса в его книге "Эффективный C ++":

Стандарт языка C ++ необычно понятно по этой теме. когда вы пытаетесь удалить производный класс объект через указатель базового класса и базовый класс имеет не виртуальный деструктор (как EnemyTarget делает), результаты не определены

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

Я предлагаю сделать его не виртуальным, только когда вы абсолютно уверены, что хотите именно так, а не полагаться на не виртуальный по умолчанию, который обеспечивают компиляторы. Вы можете не согласиться, однако (в итоге) у меня недавно произошла ужасная утечка памяти в каком-то устаревшем коде, где все, что я делал, это добавлял std :: vector в один из классов, существовавших несколько лет. Оказывается, что в одном из его базовых классов не был определен деструктор (деструктор по умолчанию пустой, не виртуальный!), И, поскольку память не выделялась таким образом, до того, как до этой точки не просочилась память. Много дней исследований и время было потрачено впустую ...

8 голосов
/ 13 июля 2009

Ури и Майкл правы - я просто добавлю, что если вам что-то мешает, вам нужно прикоснуться к двум файлам, чтобы объявить и определить деструктор, то вполне нормально определить минимальный встроенный заголовок:

class MyClass
{
   // define basic destructor right here
   virtual ~MyClass(){}

   // but these functions can be defined in a different file
   void FuncA();
   int FuncB(int etc);
}
2 голосов
/ 07 апреля 2014

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

1 голос
/ 13 июля 2009

Нет. Вы должны объявить его как виртуальный.

...