The [[noreturn]]
attribute can be applied to functions that are not meant to return. For example:
[[noreturn]] void will_throw() { throw std::runtime_error("bad, bad, bad ...."); }
But I've encountered the following situation (no, I didn't design this):
class B { public: virtual void f() { throw std::runtime_error(""); } }; class D : public B { void f() override { std::cout << "Hi" << std::endl; } };
I would really like to place the attribute [[noreturn]]
on the B::f()
declaration. But I'm unclear as to what happens to the override in the derived class. Successfully returning from a [[noreturn]]
function results in undefined behavior, and I certainly don't want that if an override also inherits the attribute.
The question: By overriding [[noreturn] virtual void B::f()
, do I inherit the [[noreturn]]
attribute?
I've looked through the C++14 standard, and I'm having trouble determining if attributes are inherited.
C++ attribute: noreturn (since C++11)Indicates that the function does not return.
Because virtual functions are called only for objects of class types, you cannot declare global or static functions as virtual . The virtual keyword can be used when declaring overriding functions in a derived class, but it is unnecessary; overrides of virtual functions are always virtual.
Use of C++ override Using the override identifier prompts the compiler to display error messages when these mistakes are made. Otherwise, the program will simply compile but the virtual function will not be overridden.
It is not mandatory for the derived class to override (or re-define the virtual function), in that case, the base class version of the function is used. A class may have virtual destructor but it cannot have a virtual constructor.
I have grepped through the standard, and there's no indication that either [[noreturn]]
specifically, or attributes more generally, are "inherited" by overriding functions.
It's hard to prove a negative, and the standard actually doesn't declare this either way but, since A::f()
and B::f()
are still distinct functions and the only behaviour described is defined in terms of functions, I think you're safe to mark A::f()
as [[noreturn]]
.
That being said, I can't imagine what useful optimisation the compiler could subsequently perform, given the dynamic dispatch.
In practice, neither g++, clang nor MSVC consider the [[noreturn]]
attribute as inherited
#include <iostream> struct B { public: [[noreturn]] virtual void f() { std::cout << "B\n"; throw 0; } }; struct D : public B { void f() override { std::cout << "D\n"; } }; int main() { try { B{}.f(); } catch(...) {} D{}.f(); B* d = new D{}; d->f(); }
which prints out "B", "D" and "D" for all three compilers.
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