C ++ деструкторы как виртуальные функции? - PullRequest
3 голосов
/ 22 июня 2011

Я только недавно прочитал, что хорошей практикой является использование деструкторов C ++ в качестве виртуальных функций [1].Почему это так?Это общая хорошая практика?Если нет, то в каких условиях / случаях деструктор должен стать виртуальной функцией?

Ссылка

  1. https://www.blackhat.com/presentations/bh-usa-07/Afek/Whitepaper/bh-usa-07-afek-WP.pdf

Ответы [ 6 ]

7 голосов
/ 22 июня 2011

Херб Саттер подробно обсуждает эту тему в своей статье "Виртуальность". Указание № 4 гласит: "Деструктор базового класса должен быть либо общедоступным и виртуальным, либо защищенным и не виртуальным."

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

4 голосов
/ 22 июня 2011

Если в базовом классе есть деструктор, и он НЕ является виртуальным, то деструктор любого дочернего класса не будет вызываться, если для указателя базового класса вызывается delete.

Это может привести к утечке памяти.

class Shape
{
public:
    Shape()
    {
        cout << "Shape constructor called" << endl;
    }
    // This destructor should be virtual!
    ~Shape()
    {
        cout << "~Shape destructor called" << endl;
    }
};

class Triangle : public Shape
{
public:
    Triangle()
    {
        cout << "Triangle constructor called" << endl;
    }
     ~Triangle()
    {
        cout << "Triangle destructor called" << endl;
    }

}

int main(int argc, char* argv[])
{
     Shape* pShape = new Triangle();
     cout << "About to call delete" << endl;
     delete pShape;
}

Это приведет к:

Конструктор треугольника с именем
Конструктор формы называется
О звонке удалить
Деструктор формы называется

Все ресурсы, которые должны быть освобождены в деструкторе треугольников, теперь просочились.

3 голосов
/ 22 июня 2011

От Effective C ++ Скотта Мейерса - «Правило предоставления базовых классов виртуальным деструкторам применимо только к полиморфным базовым классам - к базовым классам, предназначенным для управления типами производных классов через интерфейсы базовых классов»

Скорее всего, если у вас есть какие-либо виртуальные функции в базовом классе, деструктор базового класса должен быть сделан виртуальным.

Классы, не предназначенные для использования в качестве базовых классов или не предназначенные для полиморфного использования, не должны объявлять виртуальные деструкторы

2 голосов
/ 22 июня 2011

Возможно, если вся ваша иерархия классов - POD или у деструкторов нет ничего для вас, может обойтись без виртуального деструктора. Однако, как только вы захотите извлечь другие классы из вашего класса и захотите использовать их полиморфно с помощью указателя / ссылки на базу, у вас все равно появятся виртуальные функции, так что добавление виртуальных ресурсов будет небольшим деструктор, и ты никогда не знаешь, кто будет наследовать от тебя. Как только любому производному классу требуется нетривиальный деструктор , и на можно ссылаться через указатель на базу, вы должны иметь виртуальный деструктор.

Основное правило: если у вас есть какие-либо виртуальные функции, добавьте виртуальный деструктор.

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

2 голосов
/ 22 июня 2011

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

0 голосов
/ 22 июня 2011

http://blogs.msdn.com/b/oldnewthing/archive/2004/05/07/127826.aspx

В наше время, я думаю, вы должны сделать все методы виртуальными, а затем подумать, какими из них не нужно быть.

ОК, да, ясделал большую часть моего ООП в Java.

...