Virtual Default Destructors in C++

27,304

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?

Share:
27,304

Related videos on Youtube

Billy ONeal
Author by

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, 2022

Comments

  • Billy ONeal
    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 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;
    };
    

    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
      Richard Corden about 15 years
      The 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
    Billy ONeal about 15 years
    Is there any reason to use an empty destructor over a pure virtual one?
  • user1095108
    user1095108 almost 11 years
    Isn't virtual ~criterion() noexcept {} prettier?
  • user35443
    user35443 almost 10 years
    @user1095108, isn't virtual ~criterion() = default prettier?
  • Pacheco
    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
    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
    Vlad over 4 years
    why not mark it as default? Instead of "= 0" put down "= default"