virtuales una subprogramas sobreescribir pura modificador metodo funciones funcion declara como c++ c++11 inheritance noreturn

una - subprogramas virtuales c++



Anulando una funciĆ³n virtual[ (3)

Considera lo que realmente estás diciendo:

class B { public: [[noreturn]] virtual void f() { throw std::runtime_error(""); } };

Ciertamente, el lector humano, y posiblemente el compilador, interpretaría esto como un "contrato", es decir,
" f() no volveré, lo prometo"

Eso debería aplicarse a las anulaciones de f() también, o de lo contrario está incumpliendo el contrato.

El estándar podría no estar bien especificado en esto, pero incluso si funciona, lo recomendaría en función de la legibilidad.

El atributo [[noreturn]] se puede aplicar a funciones que no están destinadas a devolver. Por ejemplo:

[[noreturn]] void will_throw() { throw std::runtime_error("bad, bad, bad ...."); }

Pero me he encontrado con la siguiente situación (no, no diseñé esto):

class B { public: virtual void f() { throw std::runtime_error(""); } }; class D : public B { void f() override { std::cout << "Hi" << std::endl; } };

Realmente me gustaría colocar el atributo [[noreturn]] en la declaración B::f() . Pero no tengo claro qué sucede con la anulación en la clase derivada. El retorno exitoso de una función [[noreturn]] da como resultado un comportamiento indefinido, y ciertamente no quiero eso si una anulación también hereda el atributo.

La pregunta: Al invalidar [[noreturn] virtual void B::f() , ¿Heredo el atributo [[noreturn]] ?

He revisado el estándar C ++ 14 y tengo problemas para determinar si los atributos se heredan.


En la práctica, ni g++ , clang ni MSVC consideran el atributo [[noreturn]] como heredado

#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(); }

que imprime "B", "D" y "D" para los tres compiladores.


He revisado el estándar, y no hay ninguna indicación de que [[noreturn]] específicamente, o los atributos en general, sean "heredados" al anular las funciones.

Es difícil demostrar que es negativo, y el estándar en realidad no lo declara de ninguna manera, pero como A::f() y B::f() son funciones distintas y el único comportamiento descrito se define en términos de funciones, Creo que estás seguro de marcar A::f() como [[noreturn]] .

Dicho esto, no puedo imaginar qué optimización útil podría realizar posteriormente el compilador, dado el envío dinámico.