Почему деструктор базового класса должен быть доступен только при объявлении пользовательского конструктора? - PullRequest
16 голосов
/ 03 февраля 2012

Comeau, g ++ ( ideone ) и EDG принимают следующий код без диагностики. Visual C ++ успешно компилируется, хотя и с предупреждением C4624.

class indestructible_base
{
  ~indestructible_base();
};

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

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

Раскомментируйте конструктор, и он больше не будет компилироваться.

Возможно, это правило, что если в конструкторе возникает исключение, подобъекты должны быть уничтожены? Кажется странным, так как тело пусто и не может вызвать исключение. Тем не менее, добавьте ручку со спецификацией исключений за то, что исключение не будет выдано (throw() или noexcept), и это не имеет значения.

Почему объявленный пользователем конструктор требует доступа к деструктору базового класса, а автоматически созданный конструктор - нет?

Этот вопрос был вдохновлен: Предотвращение запуска деструктора в C ++

Ответы [ 2 ]

1 голос
/ 03 февраля 2012

Я подозреваю, что это может быть поведение, специфичное для компилятора.Вот моя теория:

Поскольку (в данном конкретном случае) неявно определенный T () является тривиальным конструктором (как определено в 12.1 (5) стандарта), компилятор недаже не пытаться сгенерировать тело для T ().Так как нет тела ctor, нет исключений, которые могли бы быть сгенерированы во время «конструирования» (которых на самом деле нет), поэтому нет необходимости генерировать вызов dtor, и, следовательно, нет необходимости генерировать тело dtorтолько для того, чтобы выяснить, что dtor базового класса является приватным.

Но как только T () становится нетривиальным (даже если он остается неявно определенным), должно быть сгенерировано тело ctor, и вы получитеОшибка.Простое добавление члена класса T с пользовательским конструктором может сделать неявно определенный T () нетривиальным.

Отдельная, но связанная проблема заключается в том, что new T() нене генерировать вызов dtor (поскольку у вас нет соответствующего delete где-либо).Напротив, если я просто заменю new T() на T dummy в вашем коде, то я получу следующее от gcc, предполагая, что теперь он выполняет полную проверку доступности dtor (как следствие необходимости генерировать вызов dtor):

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'
0 голосов
/ 03 февраля 2012

Что ж, если автоматически сгенерированный конструктор вызывает конструктор с возможным выбросом, то выдаст такую ​​же ошибку доступа .

#include <string>

class indestructible_base
{
  ~indestructible_base();
  std::string s; // <------ this may throw
};

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

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

Так что я думаю, что исключения - это ответ. В ANSI ISO IEC 14882 единственным noexcept(true) строковым конструктором является конструктор перемещения. Я считаю, это должно скомпилироваться, но ideone говорит нет.

...