Virtual Default Destructors in C++
Solution 1
Yes - the base class needs a virtual destructor, even if it's empty. If that is not done, then when something delete
's a derived object through a base pointer/reference, the derived object's member objects will not get a chance to destroy themselves properly.
Derived classes do not need to declare or define their own destructor unless they need something other than default destructor behavior.
Solution 2
The recommendation is to insert:
virtual ~criterion() {}
Starting from C++11, you can use = default;
instead of an empty body {}
.
This is to avoid problems with deleting from a base class' pointer. Otherwise you will leak memory as derived classes' destructors will not be called.
criterion *c = new fastFilter();
delete c; // leaks
Solution 3
You don't need to make the destructor abstract, just give it a empty implementation:
virtual ~criterion() { }
This way you are not forced to implement it in every child class, but still each of them will have a (inherited) virtual destructor.
Solution 4
One small change from what others have already answered:
Instead of
virtual void ~criterion() = 0;
the required version is:
virtual ~criterion() {} //Note: Removed void as destructors not allowed
// a return type
To know more about virtual destructor have a look at this link from FAQ When should my destructor be virtual?
Related videos on Youtube
Billy ONeal
Credit for Avatar image: http://www.assaultandroidcactus.com/ I'm a Microsoft Software Development Engineer on the Trustworthy Computing Team. I've worked at several security related places previously, including Malware Bytes and PreEmptive Solutions. On StackOverflow I mostly answer c++ related questions, though I occasionally forray into c# and a couple of others. I am the author of pevFind, a component of the ComboFix malware removal tool, and volunteer at BleepingComputer.com as a malware response instructor. My Twitter account is @MalwareMinigun.
Updated on July 09, 2022Comments
-
Billy ONeal almost 2 years
I've got a large set of inherited classes (criteria) which inherit from a base class (criterion). Here's
criterion
's codeclass 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; };
Some examples of derived classes from this one:
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"); }; };
Since I don't have a destructor here at all, but yet this is supposed to be a base class, do I need to insert an empty virtual destructor, I.e. like this?:
virtual void ~criterion() = 0;
If that virtual destructor declaration is needed, do all intermediate classes need one as well? I.e. would fastFilter above need a virtual destructor as well?
-
Richard Corden about 15 yearsThe above is not an empty destructor. It's a destructor that is also a pure virtual function. This has nothing to do with being empty, and in fact the destructor is special in that it must always have a definition even when it's pure virtual.
-
-
Billy ONeal about 15 yearsIs there any reason to use an empty destructor over a pure virtual one?
-
user1095108 almost 11 yearsIsn't
virtual ~criterion() noexcept {}
prettier? -
user35443 almost 10 years@user1095108, isn't
virtual ~criterion() = default
prettier? -
Pacheco almost 7 years@user35443: the "=default" didn't exist in 2009. It is something added in C++11. Yes, nowadays I think that would be the preferred option.
-
user35443 almost 7 years@Pacheco Ah, it appears so that three years ago I didn't notice the answer had been written in '09. Geez, time flies...
-
Vlad over 4 yearswhy not mark it as default? Instead of "= 0" put down "= default"