Возможный дубликат:
Когда использовать виртуальные деструкторы?
Когда должен быть ваш деструктор объекта С++ virtual
?
Возможный дубликат:
Когда использовать виртуальные деструкторы?
Когда должен быть ваш деструктор объекта С++ virtual
?
Это связано с тем, что причиной виртуального метода является то, что вы хотите использовать полиморфизм. Это означает, что вы вызовете метод указателя базового класса, и вы хотите получить самую производную реализацию - это целая точка полиморфизма.
Теперь, если у вас не было виртуального деструктора и через указатель на базовый класс вы вызываете деструктор, вы в конечном итоге вызываете деструктор базового класса. В этом случае вы хотите, чтобы полиморфизм работал и на вашем деструкторе, например, через вызов деструктора в вашем базовом классе вы хотите в конечном итоге вызвать деструктор вашего самого производного класса, а не ваш базовый класс.
class A
{
virtual void f() {}
~A() {}
}
class B : public A
{
void f() {}
~B() {}
}
A * thing = new B();
thing->f(); // calls B f()
delete thing; // calls ~A(), not what you wanted, you wanted ~B()
имеющий ~ A() виртуальный оборот полиморфизма
virtual ~A() {}
Итак, когда вы сейчас звоните
delete thing;
~ B() будет вызываться.
Вы объявляете виртуальные деструкторы при разработке класса в качестве интерфейса, например. вы ожидаете, что он будет расширен или реализован. Хорошей практикой в этом случае является наличие класса интерфейса (в смысле интерфейсов Java) с виртуальными методами и виртуальным деструктором, а затем конкретные классы реализации.
Вы можете видеть, что классы STL не имеют виртуальных деструкторов, поэтому они не должны расширяться (например, std::vector, std::string...). Если вы расширяете std::vector и вы вызываете деструктор в базовом классе с помощью указателя или ссылки, вы определенно не будете называть свой деструктор специализированного класса, что может привести к утечке памяти.
Из Часто задаваемые вопросы по стилю и технике Stroustrup С++:
Итак, когда я должен объявить деструктор виртуальная? Всякий раз, когда класс имеет не менее одной виртуальной функции. имеющий виртуальные функции показывают, что класс должен действовать как интерфейс к производным классам, и когда это так, объектом производного класса может быть уничтожен через указатель на основа.
Много дополнительной информации о когда ваш деструктор должен быть виртуальным в FAQ по С++. (спасибо Stobor)
Что такое виртуальный член? Из Часто задаваемые вопросы по С++:
[20.1] Что такое "виртуальная функция-член"?
С точки зрения ОО, это единственная самая важная особенность С++: [6.9], [6.10].
Виртуальная функция позволяет получить классы для замены реализации предоставляемый базовым классом. компилятор гарантирует, что замена всегда вызывается всякий раз, когда объект в вопрос состоит в том, класс, даже если объект доступен базовым указателем, а не производный указатель. Это позволяет алгоритмы в базовом классе должны быть заменяется в производном классе, даже если пользователи не знают о класс.
Производный класс может либо полностью заменить ( "переопределить" ) базовый класс функция-член или производный класс может частично заменить ( "увеличить" ) функция базового класса. Последний осуществляется путем получения функция члена класса вызывает базовую функция члена класса, если требуется.
Недавно я пришел к выводу, что полностью правильный ответ таков:
Руководство № 4: деструктор базового класса должны быть либо публичными, либо виртуальными, или защищенный и не виртуальный.
И, конечно, Herb Sutter дает обоснование своему требованию. Обратите внимание, что он выходит за рамки обычных ответов "когда кто-то удаляет объект производного класса с помощью указателя базового класса" и "делает ваш деструктор виртуальным, если ваш класс имеет какие-либо виртуальные функции".
Если вы (или даже можете) уничтожить объекты производного класса с помощью указателя базового класса, вам понадобится виртуальный деструктор.
Я использую подход, который, если я собираюсь извлечь из класса AT ALL, тогда он должен иметь виртуальный деструктор. В коде, который я пишу, нет случаев, когда последствия производительности виртуального деструктора влияют на производительность, и даже если это действительно не нужно сегодня, оно может понадобиться в будущем, когда класс будет изменен.
В принципе: Поместите виртуальный на всех деструкторов базового класса, если у вас нет хорошей, продуманной причины, чтобы не делать этого.
Это просто еще одно эмпирическое правило, но это не позволяет вам совершать более поздние ошибки.
Всегда.
Если я действительно не беспокоюсь о нехватке памяти и производительности на vtable, я всегда делаю ее виртуальной. Если у вас нет инструмента статического анализа, чтобы проверить, что ваш деструктор является виртуальным в правильных случаях, не стоит ошибаться и не создавать виртуального деструктора, когда это необходимо.
Объект базового класса должен иметь виртуальный деструктор, когда базовому классу необходимо выполнить собственную очистку. Это означает, что если вы выделили ресурсы в базовом классе, необходимо очистить базовый класс, объявив его виртуальным виртуальным деструктором, вы гарантируете, что эта очистка будет выполнена (если вы правильно написали очистку).
В общем, методы могут быть определены виртуальными в базовом классе, это позволит производным классам переопределять виртуальные методы, реализуя их собственную производную конкретную реализацию. Я считаю, что это наиболее ясно продемонстрировано на простом примере. Скажем, у нас есть базовый класс "Форма", теперь для всех производных классов может потребоваться способность рисовать. Объект "Shape" не будет знать, как рисовать классы, полученные из него, поэтому в классе "Shape" мы определяем функцию виртуального рисования. т.е. (virtual void draw();). Теперь в каждом базовом классе мы можем переопределить эту функцию, реализуя конкретный код чертежа (т.е. Квадрат рисуется иначе, чем круг).