为什么只有在声明自定义构造函数时才能访问基类析构函数?

时间:2012-02-03 03:15:35

标签: c++ inheritance destructor access-modifiers language-lawyer

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)这一事实并没有区别。

为什么用户声明的构造函数需要访问基类析构函数,而自动生成的构造函数不需要?

这个问题的灵感来自:Preventing a Destructor from Running in C++

2 个答案:

答案 0 :(得分:1)

我怀疑这可能是特定于编译器的行为。这是我的理论:

因为(在这种特殊情况下)隐式定义的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'

答案 1 :(得分:0)

好吧,如果自动生成的构造函数调用一个可能抛出的构造函数,那么it will give the same access error

#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)字符串构造函数是移动构造函数。我相信this 应该编译,但是ideone说不。