我们说我有一个班级
class C : public B {
public:
C() noexcept;
}
noexcept
说明符是否需要基类的相同承诺?也就是说,当我考虑使用noexcept时,我只是看一下C :: C()的行为,还是我还需要考虑B :: B()是否会抛出异常?
例如,如果B :: B抛出异常,它会传播到C :: C还是要求新类实例的代码? - 如果传播到C :: C,那么如果构造函数的基类不是noexcept,这将是避免构造函数的noexcept的一个原因。
答案 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,但是它们总会再次抛出。