Почему (C ++) виртуальные деструкторы не применяются для базового класса - PullRequest
12 голосов
/ 21 июня 2010

Деструкторы не являются виртуальными по умолчанию и не причиняют вреда, когда в них нет необходимости, что нормально.

Но в случае сценария производного класса базового класса, есть ли какой-либо вариант использования для отсутствия виртуального деструктора ? Если нет, то может быть (имеет ли это смысл) компилятор жаловаться, если класс является производным от базового класса, для которого определен открытый не виртуальный деструктор (или деструктор). И не просто предупредить об этом.

Ответы [ 4 ]

12 голосов
/ 21 июня 2010

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

Поскольку она МОЖЕТ использоваться, она разрешена.Я думаю, что необязательное предупреждение компилятора может быть хорошей идеей, но не в спецификации языка.

8 голосов
/ 21 июня 2010

Потому что вполне допустимо иметь не виртуальный деструктор. Например, если подклассы предназначены только для размещения в стеке, то нет необходимости в виртуальном деструкторе. Зачем требовать, чтобы у клиентов был весь механизм vtbl, когда класс должен быть только декоратором?

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

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

5 голосов
/ 21 июня 2010

Виртуальный деструктор необходим, только если вы выполняете полиморфное разрушение объекта через delete. Это, в свою очередь, немедленно подразумевает динамически размещенные (new -ed) объекты.

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

Если вы выделяете объекты динамически, но никогда не разрушаете их полиморфно, вам не нужен виртуальный деструктор. Это добавляет еще один набор вариантов использования, когда виртуальный destrcutor в базовом классе не нужен.

2 голосов
/ 21 июня 2010

Существуют различные проблемы с тем, что вы предлагаете, первая из которых уже рассмотрена в других ответах: вам нужны только виртуальные деструкторы, если вы собираетесь удалять с помощью указателя на базу (общая рекомендация - предоставить общедоступный виртуальныйдеструктор или защищенный не виртуальный деструктор, поскольку он будет препятствовать удалению через базовый класс).

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

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

Проблема в том, что компилятор имеет только частичное представление вашего проектаи не может на самом деле понять, что вам нужно / нужно из того, что он видит.

...