如果以下情况,则以下程序无法在 g++ 4.4 中编译:line 8
被评论。为什么?看来当我重写时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()
{
}
编译错误是:
error: looser throw specifier for ‘virtual A::~A()’
这是因为析构函数需要一个 throw() 说明符。如果您没有在类中指定它,编译器将为您的类编写它自己的默认析构函数,并且默认析构函数不会指定您不抛出异常。
这是正确的,因为 std::exception 的公共析构函数还指定throw()
~A() throw(){};
根据标准 (N3225) 12.4.4:
如果类没有用户声明的析构函数,则析构函数将隐式声明为 >defaulted (8.4)。隐含地——
声明的析构函数是其类的内联公共成员。
因此,如果您自己不声明析构函数,编译器将创建下一个析构函数。如果你所有的异常成员析构函数都在哪里nothrow
合格的,编译器可能会生成一个析构函数throw()
指定的。
~A(){};
从技术上讲,人们可以从这个析构函数中抛出异常,但这将是一种非常糟糕的编程风格,因此从std::exception
保证你不会在 a 的析构函数中抛出任何异常std::exception
派生类。
Edit较新的编译器将提供一个析构函数,该析构函数确实具有noexcept
说明符如果 std::string 的析构函数是noexcept
指定的。其他编译器也会生成一个noexcept
析构函数,如果所有成员的析构函数不抛出异常(是 noexcept 限定的)。
这是 C++11 标准第 15.4 章中强制规定的。 [规格除外]
14 隐式声明的特殊成员函数(第 12 条)应具有异常说明。如果 f 是
隐式声明的默认构造函数、复制构造函数、移动构造函数、析构函数、复制赋值
运算符,或移动赋值运算符,其隐式异常规范指定类型 ID T 当且仅
如果由 f 的隐式定义直接调用的函数的异常规范允许 T ; f 应
如果它直接调用的任何函数允许所有异常,则允许所有异常,并且f 不允许有任何例外
如果它直接调用的每个函数都不允许出现异常。 [...]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)