覆盖[[noreturn]]虚函数

Kyl*_*fel 22 c++ inheritance c++11 noreturn

[[noreturn]]属性可以应用于不打算返回的函数.例如:

[[noreturn]] void will_throw() { throw std::runtime_error("bad, bad, bad ...."); }
Run Code Online (Sandbox Code Playgroud)

但我遇到了以下情况(不,我没有设计这个):

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

class D : public B {
  void f() override { std::cout << "Hi" << std::endl; }
};
Run Code Online (Sandbox Code Playgroud)

我真的想把属性[[noreturn]]放在B::f()声明上.但是我不清楚派生类中的覆盖会发生什么.从[[noreturn]]函数成功返回会导致未定义的行为,如果重写也继承了该属性,我当然不希望这样.

问题:通过覆盖[[noreturn] virtual void B::f(),我是否继承了该[[noreturn]]属性?

我查看了C++ 14标准,我无法确定属性是否继承.

Lig*_*ica 10

我已经通过标准,并没有迹象表明,[[noreturn]]通过覆盖函数"继承"具体或更普遍的属性.

很难证明是否定的,标准实际上并没有以这种方式声明,但是,因为A::f()并且B::f()仍然是不同的函数,所描述的唯一行为是根据函数定义的,我认为你可以安全地标记A::f()[[noreturn]].

话虽如此,我无法想象在给定动态调度的情况下,编译器随后可以执行哪些有用的优化.

  • **+ 1**:属性不会被继承,因为它们([标准措辞]*"appertains"*)适用于写入它们的实体.在OPs例子中,`[[noreturn]]`适用于`void B :: f()` - `void D :: f()`是一个完全不同的实体. (4认同)

Tem*_*Rex 5

实际上,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();
}
Run Code Online (Sandbox Code Playgroud)

它为所有三个编译器打印出“B”、“D”和“D”。