派生类构造函数的Noexcept承诺:可以在基础构造函数上使用而不承诺noexcept吗?

时间:2016-04-18 21:29:04

标签: c++ c++11 exception

我们说我有一个班级

class C : public B {
  public:
    C() noexcept;
}

noexcept说明符是否需要基类的相同承诺?也就是说,当我考虑使用noexcept时,我只是看一下C :: C()的行为,还是我还需要考虑B :: B()是否会抛出异常?

例如,如果B :: B抛出异常,它会传播到C :: C还是要求新类实例的代码? - 如果传播到C :: C,那么如果构造函数的基类不是noexcept,这将是避免构造函数的noexcept的一个原因。

1 个答案:

答案 0 :(得分:8)

技术上没有要求将基类构造函数声明为noexcept,但是当被声明为noexcept的派生构造函数调用时,它不能抛出。

所以是的,你需要考虑基类构造函数是否可以抛出(异常或其他)。

  

我想问一个更好的方法就是问:下一个例外在哪里?

呼叫流程如下:

caller
  -> derived constructor (the noexcept applies to this)
    -> subobject constructors (includes bases)
    - derived constructor body (not a call, but part of the derived constructor that is executed after the subobjects are constructed)

因此,如果一个子对象(无论是基础对象还是成员对象)抛出,它首先会转到派生的构造函数,而这个构造函数不会,并且不能††吞下异常,以便它传播给调用者,如果构造函数不是noexcept。但是既然如此,std::terminate就会被调用。

如果基数确实没有按照派生的要求抛出,那么它确实符合要求并且本身可以被声明为noexcept,因此有很多理由不这样做。也许,如果基类是必须支持c ++ 03的库的一部分,而派生类可能采用更高的标准,那么它将是有意义的。

††它可以捕获一个函数try-block,但是它们总会再次抛出。