首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么基类析构函数必须只有在声明了自定义构造函数时才能访问?

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

Stack Overflow用户
提问于 2012-02-03 11:15:35
回答 2查看 713关注 0票数 17

Comeau、g++ (ideone)和EDG接受以下不带诊断的代码。尽管出现了警告C4624,Visual C++仍可成功编译。

代码语言:javascript
复制
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++

EN

回答 2

Stack Overflow用户

发布于 2012-02-04 03:03:20

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

因为(在本例中)隐式定义的T()是一个微不足道的构造函数(如标准的12.1(5)中所定义的),编译器甚至不会尝试为T()生成主体。因为没有ctor body,所以没有可能在“构造”期间生成的异常(实际上没有任何异常),所以不需要生成dtor调用,也不需要生成dtor body,只需要发现基类的dtor是私有的。

但是,一旦T()变得非常重要(即使它仍然是隐式定义的),就必须生成一个ctor主体,然后您就会得到错误。像向具有用户定义构造函数的类T添加一个成员这样简单的事情就会使隐式定义的T()变得非常重要。

另一个相关的问题是,new T()不会生成dtor调用(因为您在任何地方都没有相应的delete )。相反,如果我只是在代码中用T dummy替换new T(),那么我会从gcc得到以下结果,这表明它现在正在对dtor可访问性进行完整的检查(由于必须生成dtor调用):

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2012-02-04 01:11:22

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

代码语言:javascript
复制
#include <string>

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

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

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

所以我猜exceptions就是答案。在ANSI ISO IEC 14882中,唯一的noexcept(true)字符串构造函数是move构造函数。我认为this应该编译,但有一个人说不可以。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9123214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档