覆盖[[noreturn]]虚拟功能?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (15)

[[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标准,并且无法确定属性是否被继承。

提问于
用户回答回答于

实际上,g ++clangMSVC都不认为该[[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”。

用户回答回答于

我已经通过了标准,并且没有迹象表明,无论是[[noreturn]]特别的,还是更普遍的属性,都被“压倒一切的功能”所“继承”。

很难证明一个消极的东西,而标准实际上并没有声明这种方式,但既然A::f()并且B::f()仍然是截然不同的功能,并且所描述的唯一行为是根据函数定义的,我认为您可以安全地标记A::f()[[noreturn]]

这就是说,我无法想象在动态调度的情况下,编译器可以随后执行哪些有用的优化。

扫码关注云+社区