假设我有:
class Foo
{
public:
virtual ~Foo()=default;
};
默认析构函数的异常规范是什么?违约的析构函数是否等同于:
virtual ~Foo() {};
or
virtual ~Foo() throw() {};
or
virtual ~Foo() noexcept {};
C ++ 11标准的第15.4节说它依赖于析构函数的隐式定义直接调用的函数的异常规范。在这种情况下,没有成员,也没有基类,因此AFAIK没有隐式析构函数直接调用的函数。这是标准中的含糊不清(或遗漏)吗?
当然,这很重要,因为如果它隐式具有throw(),那么所有子类必须使用throw()声明它们的析构函数。不要告诉我在析构函数中抛出异常是个坏主意,我知道。我处理了大量未使用异常规范的遗留代码。
作为一个信息点,当我尝试:
class SubFoo : public Foo
{
public:
virtual ~SubFoo();
};
我在GCC 4.4中遇到了错误(不匹配的异常规范)(虽然我承认我可能没有正确的命令行开关),但是在使用“11”编译器的XCode 4.3中却没有。
答案 0 :(得分:4)
回到早期的同一句话(§15.4/ 14):
...它的隐式异常规范指定了type-id T当且仅当T由f的隐式定义直接调用的函数的异常规范允许时才允许; ...“
因此,如果~Foo
没有调用任何函数,它有一个隐式声明,不允许抛出任何异常。
根据§15.4/ 3:
如果符合以下条件,则两个异常规范兼容:
- 两者都是非投掷品(见下文),无论其形式如何,
这就是这种情况,因此声明是throw()
还是noexcept
并不重要 - 两者在任何情况下都是兼容的。
答案 1 :(得分:2)
标准在 C ++11§8.4.2/ 2 中很好地开始,
如果某个函数在其第一个声明中明确默认,则为 - 如果隐含的声明是,则隐含地认为是constexpr - 它被隐含地认为具有相同的异常规范,就好像它已被隐式声明(15.4),...
然而,在 C ++11§15.4/ 14 中,逻辑迅速转移,
隐式声明的特殊成员函数(第12条)应具有异常规范。如果
f
是隐式声明的默认构造函数,复制构造函数,移动构造函数,析构函数,复制赋值运算符或移动赋值运算符,则其隐式异常规范指定type-idT
if和only 如果由T
的隐式定义直接调用的函数的异常规范允许f
;如果它直接调用的任何函数允许所有异常,f
将允许所有异常,并且f
如果它直接调用的每个函数都不允许异常,则不允许异常。
在标准的“允许”含义中,它是通过异常规范明确允许的。
如果f
调用两个函数,其中一个函数指定并允许T
,其中一个函数允许所有异常,则f
必须同时指定T
和允许所有异常,这是不可能的。
所以这绝对看起来像标准中的缺陷。
我找到了相关的缺陷报告http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1351。
然而,看起来这个区域只是一个大混乱。 : - (