Виртуальные деструкторы по умолчанию в С++
У меня есть большой набор унаследованных классов (критериев), которые наследуются от базового класса (критерий). Здесь criterion
code
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");
};
};
Так как у меня вообще нет деструктора, но все же это должен быть базовый класс, мне нужно вставить пустой виртуальный деструктор, I.e. как это?:
virtual void ~criterion() = 0;
Если требуется объявление виртуального деструктора, нужны ли все промежуточные классы? То есть для fastFilter выше нужен виртуальный деструктор?
Ответы
Ответ 1
Да - базовому классу нужен виртуальный деструктор, даже если он пуст. Если это не сделано, то когда-то delete
производный объект через базовый указатель/ссылку, объекты-члены производных объектов не получат возможность правильно уничтожить себя.
Производные классы не должны объявлять или определять свой собственный деструктор, если им не требуется что-то другое, кроме поведения деструктора по умолчанию.
Ответ 2
Рекомендация заключается в том, чтобы вставить
virtual ~criterion() {}
чтобы избежать удаления из указателя базового класса. В противном случае вы будете утечка памяти, поскольку деструкторы производных классов не будут вызваны.
criterion *c = new fastFilter();
delete c; // leaks
Ответ 3
Вам не нужно делать абстрактное деструктор, просто дайте ему пустую реализацию:
virtual ~criterion() { }
Таким образом, вы не должны внедрять его в каждом дочернем классе, но каждый из них будет иметь (унаследованный) виртуальный деструктор.
Ответ 4
Небольшое изменение от того, что другие уже ответили:
Вместо
virtual void ~criterion() = 0;
требуемая версия:
virtual ~criterion() {} //Note: Removed void as destructors not allowed
// a return type
Чтобы узнать больше о виртуальном деструкторе, посмотрите на эту ссылку из FAQ Когда должен быть мой деструктор виртуальным?