[英]Overriding a [[noreturn]] virtual function
[[noreturn]]
属性可以应用于不打算返回的函数。 例如:
[[noreturn]] void will_throw() { throw std::runtime_error("bad, bad, bad ...."); }
但我遇到了以下情况(不,我没有设计这个):
class B {
public:
virtual void f() { throw std::runtime_error(""); }
};
class D : public B {
void f() override { std::cout << "Hi" << std::endl; }
};
我真的想将属性[[noreturn]]
放在B::f()
声明中。 但是我不清楚派生类中的覆盖会发生什么。 从[[noreturn]]
函数成功返回会导致未定义的行为,如果重写也继承了该属性,我当然不希望这样做。
问题:通过重写[[noreturn] virtual void B::f()
,我是否继承了[[noreturn]]
属性?
我查看了C ++ 14标准,我无法确定属性是否继承。
我已经通过标准,并没有迹象表明[[noreturn]]
具体或更普遍的属性是由覆盖函数“继承”。
很难证明是否定的,并且标准实际上并没有声明这种方式,但是,因为A::f()
和B::f()
仍然是不同的函数,所描述的唯一行为是根据函数定义的,我认为将A::f()
标记为[[noreturn]]
是安全的。
话虽如此,我无法想象在给定动态调度的情况下,编译器随后可以执行哪些有用的优化。
考虑一下你实际上在说什么:
class B
{
public:
[[noreturn]] virtual void f() { throw std::runtime_error(""); }
};
当然,人类读者,可能还有编译者,会将此解释为“契约”,即
“ f()
不会回来,我保证”
那应该适用于f()
覆盖,否则你就违反了合同。
标准可能在这方面没有详细说明,但即使它有效,我也建议根据可读性来反对它。
在实践中, 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();
}
它为所有三个编译器打印出“B”,“D”和“D”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.