Назначение деструктора virtual (т.е. создание деструктора virtual ) состоит в том, чтобы облегчить полиморфное удаление объектов с помощью delete-expression . Если ваш дизайн не требует полиморфного удаления объектов, вам не нужны виртуальные деструкторы. Обращаясь к вашему примеру, если вам когда-либо придется удалять объект типа B
через указатель типа A *
(полиморфное удаление), вам понадобится виртуальный деструктор, который находится на столь высоком уровне в иерархии, как A
. Вот так это выглядит с формальной точки зрения.
(Заметьте, кстати, как сказал Нил, важно то, как вы создаете / удаляете свои объекты классов, а не как классы управляют своей внутренней памятью.)
Что касается хорошей практики программирования ... Это зависит от ваших намерений и вашего дизайна в конце концов. Если ваши классы вообще не предназначены для полиморфизации (никаких виртуальных методов), вам не нужны виртуальные деструкторы. Если ваш класс полиморфен (имеет хотя бы один виртуальный метод), то сделать виртуальный деструктор «на всякий случай» может быть очень хорошей идеей, и в этом случае он практически не имеет производительности / потери памяти.
Последнее обычно выражается в виде довольно известного руководства по хорошей практике: если в вашем классе есть хотя бы один виртуальный метод, также сделайте деструктор виртуальным. Хотя с формальной точки зрения виртуальный деструктор там может и не понадобиться, это все же довольно хороший ориентир для подражания.
Классы, которые не имеют ресурсов, но могут образовывать полиморфные иерархии, должны всегда определять пустые виртуальные деструкторы, за исключением того, что вполне достаточно определить явный пустой (и даже чистый) виртуальный деструктор в самой основе иерархии. Все остальные деструкторы станут виртуальными автоматически, даже если они неявно определены компилятором. То есть вам не нужно явно определять пустой деструктор в каждом классе. Достаточно базы.