重写 std:exception 的析构函数

2023-11-26

如果以下情况,则以下程序无法在 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(使用前将#替换为@)

重写 std:exception 的析构函数 的相关文章

随机推荐