C++11 中默认虚拟析构函数的异常规范是什么?
What is the exception specification for a defaulted virtual destructor in C++11?
假设我有:
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 中没有。
回到前面的同一句话(§15.4/14):
。它的隐式异常规范指定类型 id T,当且仅当 T 被 f 的隐式定义直接调用的函数的异常规范所允许;"
因此,如果 ~Foo
不调用任何函数,则它具有一个隐式声明,该声明不允许引发异常。
根据§15.4/3:
在以下情况下,两个例外规范是兼容的:
- 两者都是非投掷的(见下文),无论它们的形式如何,
这里就是这种情况,所以声明是throw()
还是noexcept
并不重要——两者在任何情况下都是兼容的。
标准语言在 C++11 §8.4.2/2 中很好地开始,
如果函数在其第一个声明中显式默认,
— 如果隐式声明是,
— 它被隐式地认为具有与隐式声明相同的异常规范 (15.4),...
但是,在C++11 §15.4/14中,逻辑迅速转移,
在标准中"允许隐式声明的特殊成员函数(第 12 条)应具有例外规范。如果
f
是隐式声明的默认构造函数、复制构造函数、移动构造函数、析构函数、复制赋值运算符或移动赋值运算符,则其隐式异常规范指定类型 IDT
当且仅 如果T
被f
隐式定义直接调用的函数的异常规范所允许; 如果f
直接调用的任何函数允许所有异常,则应允许所有异常,如果f
直接调用的每个函数都不允许异常,则不允许任何异常。
"的含义中,它是关于通过异常规范明确允许的。
如果f
调用两个函数,其中一个指定并因此允许T
,另一个允许所有异常,则f
必须同时指定T
并允许所有异常,这是不可能的。
所以这绝对看起来像是标准的缺陷。
我找到了相关的缺陷报告,http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1351。
但是,看起来这个区域只是一团糟。
- 是什么导致了Unity 3D中的"错误线程异常"?
- C++异常被捕获延迟,可能导致这种情况的原因是什么?
- C++ 捕获异常后进行清理的标准方法是什么?
- 处理许多自定义异常的最佳方法是什么
- 提出异常并处理C 的某些异常类型的正确方法是什么?
- 在类中抛出异常的最佳方法是什么
- 是什么导致异常输出以及如何修复
- 与Java的InputMismatchException和IOException Handling等效的C++异常处理机制是什么
- 在C++中使用异常的可能的错误处理策略是什么,它们的后果和影响是什么
- 在使用SFML时,我会得到记忆或出于界限异常,这是什么问题
- C++ 异常中的 catch(异常)是什么意思?
- 用作类型或异常规范时"see below"是什么意思?
- procdump.exe显示的异常的含义是什么
- 复制构造函数中出现异常的可能原因是什么
- 控件的CWnd::DefWindowProc上发生Stackloverlow异常的原因是什么
- 异常代码"EXC_I386_GPFLT"的含义是什么?
- 向量::插入的异常安全保证是什么?
- 抛出的(默认)构造函数中的异常保证应该是什么
- C++11 中默认虚拟析构函数的异常规范是什么?
- C++ 我不明白我的异常是什么()行为