简体   繁体   English

覆盖[[noreturn]]虚函数

[英]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 ++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();
}

which prints out "B", "D" and "D" for all three compilers. 它为所有三个编译器打印出“B”,“D”和“D”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM