Есть ли какие-то конкретные причины для использования не виртуальных деструкторов?
Да, есть.
В основном это сводится к производительности.Виртуальная функция не может быть встроенной, вместо этого вы должны сначала определить правильную функцию для вызова (которая требует информации времени выполнения), а затем вызвать эту функцию.
В коде, чувствительном к производительности, разница между отсутствием кода и «простым»вызов функции может иметь значение.В отличие от многих языков C ++ не предполагает, что это различие тривиально.
Но почему даже можно объявить такой класс с не виртуальным деструктором?
Потому что это труднознать (для компилятора), требует ли класс виртуальный деструктор или нет.
Виртуальный деструктор требуется, когда:
- вы вызываете
delete
для указателя - для производного объекта через базовый класс
Когда компилятор видит определение класса:
- , он не может знать, что вы намереваетесь наследовать от этого класса -В конце концов, вы можете получить классы без виртуальных методов
- , но еще более утомительно: он не может знать, что вы намереваетесь вызывать
delete
для этого класса
Многие люди предполагают, что полиморфизм требует newing экземпляр, который является просто недостатком воображения:
class Base { public: virtual void foo() const = 0; protected: ~Base() {} };
class Derived: public Base {
public: virtual void foo() const { std::cout << "Hello, World!\n"; }
};
void print(Base const& b) { b.foo(); }
int main() {
Derived d;
print(d);
}
В этом случае нет необходимости платить за виртуальный деструктор, потому что в нем не задействован полиморфизмВед во время разрушения.
В конце концов, это вопрос философии.Там, где это целесообразно, по умолчанию C ++ выбирает производительность и минимальное обслуживание (основным исключением является RTTI).
Что касается предупреждения.Есть два предупреждения, которые можно использовать для выявления проблемы:
-Wnon-virtual-dtor
(gcc, Clang): предупреждает всякий раз, когда класс с виртуальной функцией не объявляет виртуальный деструктор, если толькоДеструктор в базовом классе выполнен protected
.Это пессимистическое предупреждение, но, по крайней мере, вы ничего не пропустите.
-Wdelete-non-virtual-dtor
(Clang, перенесен также на gcc ): предупреждает всякий раз, когда delete
вызывается по указателю на класс, который имеет виртуальные функции, но не имеет виртуального деструктора, если класс не помечен как final
.Он имеет 0% ложных срабатываний, но предупреждает «поздно» (и, возможно, несколько раз).