C++ 超越std的析构函数:异常

C++ 超越std的析构函数:异常,c++,exception,exception-handling,destructor,throw,C++,Exception,Exception Handling,Destructor,Throw,如果注释了第8行,则以下程序不会在g++4.4中编译。为什么?似乎当我重写std::exception构造函数时,我也必须重写它的析构函数。这是什么原因 #include<iostream> #include<exception> using namespace std; class A : public exception { public: A(string msg) : _msg(msg) {} //~A() throw(){};

如果注释了
第8行
,则以下程序不会在g++4.4中编译。为什么?似乎当我重写
std::exception
构造函数时,我也必须重写它的析构函数。这是什么原因

#include<iostream>
#include<exception>
using namespace std;

class A : public exception {
public:
    A(string msg) : _msg(msg) {}
    //~A() throw(){};                     // line 8
    const char* what() const throw() { return _msg.c_str();}    
private:
    string _msg;
};

int main()
{
}

这是因为析构函数需要throw()说明符。如果您没有在类中指定它,编译器会为您的类编写自己的默认析构函数,而默认析构函数不会指定您不抛出异常

这是正确的,因为std::exception的公共析构函数也指定了
throw()

根据标准(N3225)12.4.4:

如果类没有用户声明的析构函数,则析构函数将隐式声明为>defaulted(8.4)。含蓄地- 声明的析构函数是其类的内联公共成员

因此,如果您自己不声明析构函数,编译器将创建下一个析构函数。如果
nothrow
中的所有异常成员析构函数都符合条件,则编译器可能会生成指定了
throw()
的析构函数

~A(){};
从技术上讲,可以从这个析构函数中抛出异常,但这将是非常糟糕的编程风格,因此从
std::exception
派生的异常可以保证在
std::exception
派生类的析构函数中不会抛出任何异常

编辑 如果std::string的析构函数是
noexcept
指定的,则较新的编译器将提供一个具有
noexcept
说明符的析构函数。如果所有成员的析构函数都不抛出异常(符合noexcept条件),那么其他编译器也将生成一个
noexcept
析构函数。 这是C++11标准在第15.4章中规定的。[规格除外]

14隐式声明的特殊成员职能(第12条)应具有例外规定如果f是 隐式声明的默认构造函数、复制构造函数、移动构造函数、析构函数、复制赋值 运算符,或移动赋值运算符,其隐式异常指定指定类型id T当且仅当 如果f的隐式定义直接调用的函数的异常规范允许T;f应 如果直接调用的函数允许所有异常,则允许所有异常,f不允许任何异常 如果它直接调用的每个函数都不允许出现异常。[…]


编译器是否报告错误消息?如果是这样,为什么不在问题中?@DavidHeffernan,thanx,fixedIt在他的问题的底部(可能是在编辑之后)。当然,这与4.8.1相同,因为默认析构函数没有此处要求的throw说明符。@Laszlo是的,在编辑它并添加错误之后,问题就在这里了。这并不是全部。如果编译器生成的析构函数直接调用的所有函数都不允许出现异常(非静态数据成员的析构函数和基类的析构函数),则编译器生成的析构函数将具有
nothrow
规范。该示例未能编译,因为
std::string
成员的析构函数未标记为
throw()
。试着用
constchar*
替换它,看看区别。两者都可以,编译OP的代码就可以了。也就是说,在C++11中。我不知道这是否在C++03之后有所改变。如果您不介意的话,我添加了标准中的规范性引用。和+1。你不应该突出显示“nothrow”,好像它是一个关键字。有一个
std::nothrow
类型的默认对象
std::nothrow\u t
用于“非抛出
new
”,但“非抛出异常规范”要么是
throw()
[在C++98/03中,在C++11中不推荐]要么[在C++11中]
noexcept
(或者
noexcept(true)
,或者任何
noexcept(
CE
其中常量表达式CE的计算结果为
true
(包括有趣的
noexcept(noexcept(
expression
其中表达式可以在编译时被证明不抛出))。@gx_I在noexcept中没有更改任何行
~A() throw(){};
~A(){};