Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why must a base class destructor be accessible only when a custom constructor is declared?

Comeau, g++ (ideone) and EDG accept the following code without diagnostic. Visual C++ compiles successfully, albeit with warning C4624.

class indestructible_base
{
  ~indestructible_base();
};

class T : indestructible_base
{
public:
  //T() {}
};

int main(void) { new T(); }

Uncomment the constructor and it no longer compiles.

Perhaps it's the rule that if an exception occurs inside the constructor, subobjects must be destroyed? Seems odd, since the body is empty and can't cause an exception. Even so, add an exception-specification vouching for the fact that no exception will be thrown (throw() or noexcept) and it makes no difference.

Why does a user-declared constructor require access to the base class destructor, while an automatically-generated constructor does not?

This question was inspired by: Preventing a Destructor from Running in C++

like image 414
Ben Voigt Avatar asked Feb 03 '12 03:02

Ben Voigt


People also ask

Can we declare base class constructor or destructor as virtual If yes then why we want to do?

Virtual Constructor in C++ In C++, the constructor cannot be virtual, because when a constructor of a class is executed there is no virtual table in the memory, means no virtual pointer defined yet. So, the constructor should always be non-virtual. But virtual destructor is possible.

In which case is it mandatory to provide a destructor in a class?

Destructor function is called automatically when the object goes out of scope. When a class contains dynamic object then it is mandatory to write a destructor function to release memory before the class instance is destroyed this must be done to avoid memory leak.

Why do we need a destructor in C++?

Destructors are usually used to deallocate memory and do other cleanup for a class object and its class members when the object is destroyed. A destructor is called for a class object when that object passes out of scope or is explicitly deleted.

What is a destructor and how it is defined in a class?

A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to delete . A destructor has the same name as the class, preceded by a tilde ( ~ ). For example, the destructor for class String is declared: ~String() .


1 Answers

I suspect that this might be compiler-specific behavior. Here's my theory:

Because (in this particular case) an implicitly-defined T() is a trivial constructor (as defined in 12.1(5) of the standard), the compiler doesn't even attempt to generate a body for T(). Since there's no ctor body, there are no exceptions that could possibly be generated during "construction" (of which there isn't any, really), so there's no need to generate a dtor call, and so no need to generate a dtor body, only to find out that the base class's dtor is private.

But as soon as T() becomes non-trivial (even if it remains implicitly-defined), a ctor body must be generated, and you get the error. Something as simple as adding a member to class T that has a user-defined constructor would make the implicitly-defined T() become non-trivial.

A separate, but related, issue is that new T() doesn't generate a dtor call (since you don't have a corresponding delete anywhere). In contrast, if I just replace new T() with T dummy in your code, then I get the following from gcc, suggesting that it's now doing the full check for dtor accessibility (as a consequence of having to generate a dtor call):

test.cpp: In destructor 'T::~T()':
test.cpp:3: error: 'indestructible_base::~indestructible_base()' is private
test.cpp:7: error: within this context
test.cpp: In function 'int main()':
test.cpp:12: note: synthesized method 'T::~T()' first required here
test.cpp:12: warning: unused variable 'dummy'
like image 70
jjlin Avatar answered Oct 05 '22 07:10

jjlin