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(){};