派生类构造函数上的Noexcept promise:可以在没有对基构造函数上的Noexcept进行承诺的情况下使用

Noexcept promise on derived class constructor: can that be used without promising noexcept on base constructor?

本文关键字:Noexcept 构造函数 承诺 情况下 promise 派生      更新时间:2023-10-16

假设我有一个类

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

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

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

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

因此,是的,您确实需要考虑基类构造函数是否会抛出(异常或其他)。

我想问我这个问题的一个更好的方法是:例外下一步会去哪里?

呼叫流程如下:

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块捕获,但这些块总是会再次抛出。

相关文章: