Подтвердить что ты не робот

Почему виртуальные деструкторы (С++) не применяются для базового класса

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

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

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

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

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