[[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标准,但在确定属性是否继承时遇到了问题。
发布于 2015-09-19 03:33:47
实际上,无论是、还是都不认为[[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“。
发布于 2015-09-18 23:58:06
我仔细阅读了这个标准,没有迹象表明[[noreturn]]
或者更一般的属性是通过重写函数来“继承”的。
很难证明是否定的,标准实际上也没有以任何一种方式声明这一点,但是,由于A::f()
和B::f()
仍然是不同的函数,并且所描述的唯一行为是根据函数定义的,所以我认为将A::f()
标记为[[noreturn]]
是安全的。
这就是说,我不能想象编译器在动态分派的情况下可以执行什么有用的优化。
发布于 2015-09-19 00:12:49
想一想你实际在说什么:
class B
{
public:
[[noreturn]] virtual void f() { throw std::runtime_error(""); }
};
当然,人类读者,也可能是编译器,会将其解释为“契约”,即
"f()
不会回来了,我保证“
然后,这也应该适用于f()
的覆盖,否则你就违反了合同。
标准可能在这一点上规定得不够,但即使它可以工作,基于可读性,我也不建议使用它。
https://stackoverflow.com/questions/32655526
复制相似问题