首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在函数的C++11中,"final“关键字的用途是什么?

在函数的C++11中,"final“关键字的用途是什么?
EN

Stack Overflow用户
提问于 2012-01-12 02:25:34
回答 6查看 116.4K关注 0票数 160

C++11中用于函数的final关键字的用途是什么?我知道它可以防止派生类重写函数,但如果是这样的话,将final函数声明为非虚函数还不够吗?我还漏掉了什么吗?

EN

回答 6

Stack Overflow用户

发布于 2013-07-12 06:43:26

"final“还允许编译器优化绕过间接调用:

代码语言:javascript
复制
class IAbstract
{
public:
  virtual void DoSomething() = 0;
};

class CDerived : public IAbstract
{
  void DoSomething() final { m_x = 1 ; }

  void Blah( void ) { DoSomething(); }

};

使用"final",编译器可以直接从Blah()内部调用CDerived::DoSomething(),甚至是内联调用。如果没有它,它必须在Blah()内部生成一个间接调用,因为Blah()可能会在已覆盖DoSomething()的派生类中被调用。

票数 55
EN

Stack Overflow用户

发布于 2013-09-13 05:25:37

我喜欢的'final‘关键字的用例如下:

代码语言:javascript
复制
// This pure abstract interface creates a way
// for unit test suites to stub-out Foo objects
class FooInterface
{
public:
   virtual void DoSomething() = 0;
private:
   virtual void DoSomethingImpl() = 0;
};

// Implement Non-Virtual Interface Pattern in FooBase using final
// (Alternatively implement the Template Pattern in FooBase using final)
class FooBase : public FooInterface
{
public:
    virtual void DoSomething() final { DoFirst(); DoSomethingImpl(); DoLast(); }
private:
    virtual void DoSomethingImpl() { /* left for derived classes to customize */ }
    void DoFirst(); // no derived customization allowed here
    void DoLast(); // no derived customization allowed here either
};

// Feel secure knowing that unit test suites can stub you out at the FooInterface level
// if necessary
// Feel doubly secure knowing that your children cannot violate your Template Pattern
// When DoSomething is called from a FooBase * you know without a doubt that
// DoFirst will execute before DoSomethingImpl, and DoLast will execute after.
class FooDerived : public FooBase
{
private:
    virtual void DoSomethingImpl() {/* customize DoSomething at this location */}
};
票数 9
EN

Stack Overflow用户

发布于 2012-01-12 02:32:52

final添加了一个明确的意图,不让你的函数被覆盖,如果违反了这一点,将导致编译器错误:

代码语言:javascript
复制
struct A {
    virtual int foo(); // #1
};
struct B : A {
    int foo();
};

按照代码的原样,它会进行编译,并且B::foo会覆盖A::foo。顺便说一句,B::foo也是虚拟的。但是,如果我们将#1更改为virtual int foo() final,则这是一个编译器错误,并且我们不允许在派生类中进一步重写A::foo

注意,这不允许我们“重新打开”一个新的层次结构,也就是说,没有办法使B::foo成为一个新的、不相关的函数,它可以独立地位于新的虚拟层次结构的头部。一旦一个函数是最终的,它就永远不能在任何派生类中再次声明。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8824587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档