﻿# V599\. The virtual destructor is not present, although the 'Foo' class contains virtual functions\.

Анализатор обнаружил потенциальную ошибку, связанную с отсутствием в базовом классе виртуального деструктора\.

Чтобы анализатор выдал предупреждение V599 необходимо, чтобы выполнились следующие условия:

1. Объект класса уничтожается с помощью оператора `delete`\.
1. Класс имеет хотя бы одну виртуальную функцию\.

Наличие виртуальных функций говорит о том, что класс могут использовать полиморфно\. В этом случае виртуальный деструктор необходим, чтобы корректно разрушить объект\.

Рассмотрим пример кода\.

```cpp
class Father
{
public:
  Father() { .... }
  ~Father() { .... } 
  virtual void Foo() { .... }
};

class Son : public Father
{
public:
  int *buffer;
  Son() : Father() { buffer = new int[1024]; }
  ~Son() { delete[] buffer; }
  virtual void Foo() { .... }
};

....
Father *object = new Son();
delete object;              // Calls object->~Father(),
                            // not object->~Son()!!
```

Нижеприведённый код является некорректным и приводит к утечке памяти\. В момент уничтожения объекта \(`delete object;`\) вызывается только деструктор в классе `Father`\. Чтобы вызвать деструктор класса 'Son' необходимо сделать деструктор виртуальным\. 

Корректный код:

```cpp
class Father
{
public:
  Father() { .... }
  virtual ~Father() { .... } 
  virtual void Foo() { .... }
};
```

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

Намного больше проблем позволяют выявлять предупреждения компиляторов, например, [`C4265`](https://www.microsoft.com/en-us/download/details.aspx?id=55984) в MSVC и `Wdelete-non-virtual-dtor` в [GCC](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wall)/[Clang](https://clang.llvm.org/docs/DiagnosticsReference.html#wdelete-non-virtual-dtor)\. Это очень полезные предупреждения, но по умолчанию они выключены\. Возможная причина: они дают много срабатываний в коде, где используется паттерн [примесь](https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%81%D1%8C_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)) \(подмешивание, mixin\)\. При использовании этого паттерна возникает множество интерфейсных классов\. Они содержат виртуальные функции, но виртуальный деструктор в них не нужен\.

Можно сказать, что диагностическое правило V599 является частным случаем описанных ранее предупреждений компиляторов\. Оно дает меньше ложных срабатываний, но, к сожалению, позволяет выявить меньшее количество дефектов\. Если вы хотите провести более тщательный анализ своего кода, то включите предупреждение C4265\.

P\.S\. К сожалению, **всегда** объявлять деструктор виртуальным не является идеальной практикой программирования\. Это приводит к дополнительным накладным расходам, так как в классе появляется указатель на таблицу виртуальных методов\.

P\.P\.S\. Родственным диагностическим правилом является [V689](https://pvs-studio.ru/ru/docs/warnings/v689/)\.

Дополнительная информация:

1. Wikipedia\. [Таблица виртуальных методов\.](https://ru.wikipedia.org/wiki/%D0%A2%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0_%D0%B2%D0%B8%D1%80%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D0%BE%D0%B2) 
1. Wikipedia\. [Виртуальный метод \(виртуальная функция\)\.](https://ru.wikipedia.org/wiki/%D0%92%D0%B8%D1%80%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4)
1. Wikipedia\. [Деструктор\.](https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D0%BE%D1%80)
1. Сергей Олендаренко\. [Виртуальные функции и деструктор\.](https://habr.com/ru/articles/64280/)