What is this error message about implicitly deleted virtual destructors?

Frigo picture Frigo · Sep 28, 2011 · Viewed 14.8k times · Source

I've just updated GCC from (I think) 4.5.6 to 4.6.1, under Windows, MinGW. Suddenly my NonInstantiable base class (from which you inherit with public virtual to prevent instantiation) refuses to work with the following and similar error messages:

#ifndef Frigo_Lang_NonInstantiable
#define Frigo_Lang_NonInstantiable

namespace Frigo
{
namespace Lang
{

/**
*   Inherit from this class if you want to make a non-instantiable class. Most
*   useful for static classes. It seems every inheritance combination
*   (public/protected/private, non-virtual/virtual) shuts off instantiation in
*   all subclasses as well.
**/

class NonInstantiable
{
private:
/*  Private Classes  */

    /**
    *   A dummy class to prevent GCC warnings about virtual
    *   constructors/destructors and no friends
    **/
    class NonInstantiableDummy { };

/*  Private Constructors  */

    /**
    *   Private constructor to prevent instantiation
    **/
    NonInstantiable() { }

    /**
    *   Private destructor to prevent instantiation on the stack. Virtual to
    *   prevent GCC warnings
    **/
    virtual ~NonInstantiable() { }

/*  Friends  */
    friend class NonInstantiableDummy;
};

}
}

#endif

Errors:

/code/Frigo/Util/Arrays:40:7: error: deleted function 'virtual Frigo::Util::Arrays::~Arrays()'
/code/Frigo/Lang/Object:37:11: error: overriding non-deleted function 'virtual Frigo::Lang::Object::~Object()'
/code/Frigo/Util/Arrays:40:7: error: 'virtual Frigo::Util::Arrays::~Arrays()' is implicitly deleted because the default definition would be ill-formed:
/code/Frigo/Lang/NonInstantiable:39:11: error: 'virtual Frigo::Lang::NonInstantiable::~NonInstantiable()' is private
/code/Frigo/Util/Arrays:40:7: error: within this context
/code/Frigo/Lang/NonInstantiable:39:11: error: 'virtual Frigo::Lang::NonInstantiable::~NonInstantiable()' is private
/code/Frigo/Util/Arrays:40:7: error: within this context
/code/Frigo/Util/Arrays:40:7: error: deleted function 'virtual Frigo::Util::Arrays::~Arrays()'
/code/Frigo/Lang/NonInstantiable:39:11: error: overriding non-deleted function 'virtual Frigo::Lang::NonInstantiable::~NonInstantiable()'

I suspect it is because I do not create any destructors, virtual or otherwise, in the child classes, and this somehow conflicts with the private virtual destructor of NonInstantiable, but I need confirmation. And a solution how to fix my NonInstantiable class to suppress these errors, but still work.

Answer

Mark B picture Mark B · Sep 28, 2011

Parent destructors always need to be callable from a child class (because this happens automatically) and so parent class destructors can't be private.

Just make your NonInstantiable's destructor protected.

Also note that a child class could circumvent the parent as written by explicitly (accidentally?) calling into its public compiler-generated copy constructor.

EDIT: I should add as an aside that you might want to consider your need for a non-instantiable class here. I personally believe that a combination of free functions and anonymous-namespace variables would be a cleaner way of doing this.