[英]Overriding a [[noreturn]] virtual function
The [[noreturn]]
attribute can be applied to functions that are not meant to return. [[noreturn]]
属性可以应用于不打算返回的函数。 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. 我真的想将属性
[[noreturn]]
放在B::f()
声明中。 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. 从
[[noreturn]]
函数成功返回会导致未定义的行为,如果重写也继承了该属性,我当然不希望这样做。
The question: By overriding [[noreturn] virtual void B::f()
, do I inherit the [[noreturn]]
attribute? 问题:通过重写
[[noreturn] virtual void B::f()
,我是否继承了[[noreturn]]
属性?
I've looked through the C++14 standard, and I'm having trouble determining if attributes are inherited. 我查看了C ++ 14标准,我无法确定属性是否继承。
I have grepped through the standard, and there's no indication that either [[noreturn]]
specifically, or attributes more generally, are "inherited" by overriding functions. 我已经通过标准,并没有迹象表明
[[noreturn]]
具体或更普遍的属性是由覆盖函数“继承”。
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]]
. 很难证明是否定的,并且标准实际上并没有声明这种方式,但是,因为
A::f()
和B::f()
仍然是不同的函数,所描述的唯一行为是根据函数定义的,我认为将A::f()
标记为[[noreturn]]
是安全的。
That being said, I can't imagine what useful optimisation the compiler could subsequently perform, given the dynamic dispatch. 话虽如此,我无法想象在给定动态调度的情况下,编译器随后可以执行哪些有用的优化。
Consider what you are actually saying: 考虑一下你实际上在说什么:
class B
{
public:
[[noreturn]] virtual void f() { throw std::runtime_error(""); }
};
Certainly the human reader, and possibly the compiler, would interpret this as a 'contract', ie 当然,人类读者,可能还有编译者,会将此解释为“契约”,即
" f()
wont return, I promise" “
f()
不会回来,我保证”
That should then apply to overrides of f()
too, or else you are breaking the contract. 那应该适用于
f()
覆盖,否则你就违反了合同。
The standard might be underspecified on this, but even if it works, I would recommend against it based on readability. 标准可能在这方面没有详细说明,但即使它有效,我也建议根据可读性来反对它。
In practice, neither g++ , clang nor MSVC consider the [[noreturn]]
attribute as inherited 在实践中, g ++ , clang和MSVC都不认为
[[noreturn]]
属性是继承的
#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. 它为所有三个编译器打印出“B”,“D”和“D”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.