What is this error message about implicitly deleted virtual destructors?

16,193

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.

Share:
16,193
Frigo
Author by

Frigo

Updated on June 07, 2022

Comments

  • Frigo
    Frigo about 2 years

    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.

    • Captain Giraffe
      Captain Giraffe over 12 years
      A private destructor, thats seems just mean to me. Care to explain you comments in your code from the link? Edit: Mark B's answer explains it.
    • Frigo
      Frigo over 12 years
      Well, the class tries to prevent instantiation (in subclasses as well) by declaring a private constructor and destructor. The destructor needs to be virtual otherwise GCC whines at inheritance. The friend inner class need to be there as well otherwise GCC whines.
    • Captain Giraffe
      Captain Giraffe over 12 years
      What is your use-case? Why do you need this? I'm very curious.
    • Frigo
      Frigo over 12 years
      Just to prevent accidental instantiation of static classes (aka "storage classes" aka "utility classes"). There is some static keyword to mark such classes, but IIRC it allows only static methods, it throws a fit when it sees a static variable.
    • Mike Seymour
      Mike Seymour over 12 years
      @Frigo: in C++, you'd usually use a namespace for that, and only define a class when you actually want an instantiable type. "Static classes" only make sense in languages that force you to put everything in a class.
    • Frigo
      Frigo over 12 years
      Sometimes I need static variables and methods that are private (for example, the internals of Arrays::quicksort). Namespace scope variables and methods are not perfect, they are accessible by everyone and this can cause complications. I prefer them being in classes. Anonymous namespaces help the situation somewhat, but their advantages are negligible.
  • Frigo
    Frigo over 12 years
    Good call at making the destructor private. Is this due to some recent language change part of C++11 or just a GCC bugfix to better conform? Also, created a private copy constructor as well just to be sure ;)