Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why do gcc/clang complain about the base class having a protected destructor, but not about the derived class?

The following code compiles with Visual Studio 2019, but not with gcc and clang. Defining the variable b causes an error with the latter two compilers.

#include <iostream>

class base
{
public:
    constexpr base(int i) : m_i(i) {}

    constexpr int i() const { return m_i; }

protected:
    ~base() = default; // Forbid polymorphic deletion
private:
    const int m_i;
};

class derived final : public base
{
public:
    constexpr derived() : base(42) {}
};

// Defining b compiles with Visual Studio 2019,
// but does not with gcc and clang.
// gcc 11.2:    error: 'base::~base()' is protected within this context
// clang 13.0:  error: variable of type 'const base' has protected destructor
constexpr base b(41);

// Defining d compiles with all 3 compilers.
constexpr derived d;

int main()
{
    std::cout << b.i() << std::endl;
    std::cout << d.i() << std::endl;
}

Which of the compilers are right? Microsoft, which compiles the program, or gcc and clang, which do not?

And if gcc and clang are right, why does the error show up for b, but not for d?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

A destructor is a member-function, so it cannot be called in context where you would not be able to call other member functions.
The context of the call is the context of the construction of the object (see below), so in your case you cannot call ~base() outside of base (or a class derived from base), which is why you get the error with gcc and clang (which are correct).

[class.dtor#15] […] In each case, the context of the invocation is the context of the construction of the object. […]

The error shows up for b and not for d because the implicitly declared destructor of derived is public:

[class.dtor#2] If a class has no user-declared prospective destructor, a prospective destructor is implicitly declared as defaulted ([dcl.fct.def]).
An implicitly-declared prospective destructor is an inline public member of its class.

Making the destructor of base protected or private does not make the destructor of child classes protected or private by default, you simply get the implicitly defined destructor, which is public.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading