Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why derived constructor needs base destructor?

Tags:

c++

class A{
  public:
   A();
  private:
   ~A();
};

class B:public A{
  public:
    B(){};
  private:
   ~B();
};

int main()
{
  return 0;
}

I've got a compile error like this:

test.cpp: In constructor 'B::B()':
test.cpp:5:4: error: 'A::~A()' is private
test.cpp:10:8: error: within this context

I know the derived constructor need to invoke the base destructor, hence I set A::A() as public. However, why the compiler complains that it need public A::~A() either?

like image 754
HP Chen Avatar asked Sep 25 '14 10:09

HP Chen


2 Answers

The closest specification I could find is here - 12.4.10 class.dtor:

... A program is ill-formed if an object of class type or array thereof is declared and the destructor for the class is not accessible at the point of the declaration.

class B is not able to access private: ~A(), but is implicitly declaring class A because it is a base class (it is almost the same as declaring first member variable - except empty base optimization).

I am not a language lawyer and not a native speaker, but the inaccessible base class destructor seems to be the problem and the above may explain why the error points to the constructor B() (the compiler may perform the checks when they are really needed, not before).

The destructor ~A() needs to be made at least protected or B friend of A.

like image 117
firda Avatar answered Oct 12 '22 15:10

firda


The C++ standards committee core working group defect report 1424 (submitted by Daniel Krügler on 2011-12-07) says:

The current specification does not appear to say whether an implementation is permitted/required/forbidden to complain when a sub-object's destructor is inaccessible.

This is fixed in C++14 by the addition of the notion of a destructor being potentially invoked. The current draft standard section 12.6.2(10) says:

In a non-delegating constructor, the destructor for each direct or virtual base class and for each non-static data member of class type is potentially invoked (12.4).

[ Note: This provision ensures that destructors can be called for fully-constructed sub-objects in case an exception is thrown (15.2). —end note ]

And in 12.4(11):

A destructor is potentially invoked if it is invoked or as specified in 5.3.4 and 12.6.2. A program is ill-formed if a destructor that is potentially invoked is deleted or not accessible from the context of the invocation.

like image 29
Oktalist Avatar answered Oct 12 '22 15:10

Oktalist