Виртуальные деструкторы по умолчанию в C ++ - PullRequest
16 голосов
/ 06 мая 2009

У меня есть большой набор унаследованных классов (критериев), которые наследуются от базового класса (критерия). Вот код criterion

class criterion
{
public:
    virtual unsigned __int32 getPriorityClass() const = 0;
    virtual BOOL include(fileData &file) const = 0;
    virtual void reorderTree() = 0;
    virtual unsigned int directoryCheck(const std::wstring& directory) const = 0;
    virtual std::wstring debugTree() const = 0;
};

Некоторые примеры производных классов от этого:

class fastFilter : public criterion
{
public:
    void reorderTree() {};
    unsigned int  directoryCheck(const std::wstring& /*directory*/) const { return DIRECTORY_DONTCARE; };
    unsigned __int32 getPriorityClass() const { return PRIORITY_FAST_FILTER; };
};

class isArchive : public fastFilter
{
public:
    BOOL include(fileData &file) const
    {
        return file.getArchive();
    }
    std::wstring debugTree() const
    {
        return std::wstring(L"+ ISARCHIVE\n");
    };
};

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

virtual void ~criterion() = 0;

Если требуется объявление виртуального деструктора, нужен ли он всем промежуточным классам? То есть понадобится ли для fastFilter виртуальный деструктор?

Ответы [ 4 ]

39 голосов
/ 06 мая 2009

Да - базовому классу нужен виртуальный деструктор, даже если он пуст. Если этого не сделать, то когда что-то delete является производным объектом через базовый указатель / ссылку, объекты-члены производного объекта не получат шанса уничтожить себя должным образом.

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

24 голосов
/ 06 мая 2009

Рекомендуется вставить

virtual ~criterion() {}

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

criterion *c = new fastFilter();
delete c; // leaks
12 голосов
/ 06 мая 2009

Вам не нужно делать деструктор абстрактным, просто дайте ему пустую реализацию:

virtual ~criterion() { }

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

7 голосов
/ 06 мая 2009

Одно небольшое изменение от того, что другие уже ответили:

Вместо

virtual void ~criterion() = 0;

необходимая версия:

    virtual ~criterion() {}  //Note: Removed void as destructors not allowed 
                             //  a return type

Чтобы узнать больше о виртуальном деструкторе, перейдите по этой ссылке из FAQ Когда мой деструктор должен быть виртуальным?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...