Let's say I have a class
class C : public B {
public:
C() noexcept;
}
Does the noexcept
specifier require the same promise by the base class? That is, when I am considering using noexcept, do I just look at the behavior of C::C() or do I also need to consider whether B::B() may throw exceptions?
For example, if B::B throws an exception, does that propagate to C::C or to the code that was asking for a new class instance? -- If propagating to C::C, that would be one reason to avoid noexcept for the constructor if a base class is not noexcept for the constructor.
There is technically† no requirement for the base class constructor to be declared noexcept, but it must not throw, when called by a derived constructor that is declared noexcept.
So yes, you do need to consider whether the base class constructor may throw (exceptions or otherwise).
I guess a better way of asking my question is: where does the exception go next?
The calls flow like this:
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)
So, if a subobject (whether it be a base or a member) constructor throws, it first goes to the derived constructor, which doesn't and can't†† swallow the exception so it would propagate to the caller, if the constructor wasn't noexcept. But since it is, std::terminate
gets called.
†If the base doesn't indeed throw as required by the derived, then it does meet the requirement and can itself be declared noexcept so there is rarly reason not to do so. Perhaps, if the base class is part of a library that must support c++03, while the derived class may assume a later standard, it would make sense.
††It can catch with a function-try-block, but those will always throw again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With