以下似乎是在我尝试的几个编译器上编译的:
class A
{
public:
virtual void foo() throw() = 0;
};
class B : public A
{
public:
virtual void foo() noexcept override { }
};
似乎可以使用较新的noexcept规范覆盖throw()函数。我也尝试了相反的方法(用throw()覆盖noexcept)它似乎工作。这是为什么?这是未定义的行为还是允许的?
请注意,代码生成受noexcept vs throw()的影响。它们也没有相同的行为,因为noexcept调用与throw()不同的终止函数。一个理想的答案会说出行为的差异以及在这种情况下它们为什么或不重要。
答案 0 :(得分:3)
您甚至可以在不覆盖的情况下执行此操作:
void f() throw();
void f() noexcept { throw 1; }
[except.spec]/9明确指出定义上的规范可以控制发生的事情:
每当抛出类型E的异常并搜索处理程序时 ([except.handle])遇到一个函数的最外面的块 异常规范,不允许E,那么,
如果函数定义具有动态异常规范,则为 调用函数
std::unexpected()
([except.unexpected]),否则,调用函数
std::terminate()
([except.terminate])。
这不是一个问题,因为无论是对被叫方进行了哪些特殊处理,而不是来电者;所有调用者需要知道的是,任何例外都不会离开函数。
答案 1 :(得分:2)
这是未定义的行为还是允许的? 这是允许的。
来自C ++标准:
如果虚函数具有异常规范,则全部 任何覆盖的函数的声明,包括定义 任何派生类中的虚函数只允许例外 基类的异常规范允许的 虚函数,除非重写函数定义为 删除。
实际上:您可以覆盖派生类中的方法,并指定除基类指定的规则之外的新规则。
在您的示例throw()
中,noexcept
是等效的。