What is the purpose of the “final” keyword in C++1

2020-01-29 03:09发布

What is the purpose of the final keyword in C++11 for functions? I understand it prevents function overriding by derived classes, but if this is the case, then isn't it enough to declare as non-virtual your final functions? Is there another thing I'm missing here?

标签: c++ c++11 final
10条回答
干净又极端
2楼-- · 2020-01-29 03:59

Final keyword in C++ when added to a function, prevents it from being overridden by a base class. Also when added to a class prevents inheritance of any type. Consider the following example which shows use of final specifier. This program fails in compilation.

#include <iostream>
using namespace std;

class Base
{
  public:
  virtual void myfun() final
  {
    cout << "myfun() in Base";
  }
};
class Derived : public Base
{
  void myfun()
  {
    cout << "myfun() in Derived\n";
  }
};

int main()
{
  Derived d;
  Base &b = d;
  b.myfun();
  return 0;
}

Also:

#include <iostream>
class Base final
{
};

class Derived : public Base
{
};

int main()
{
  Derived d;
  return 0;
}
查看更多
我只想做你的唯一
3楼-- · 2020-01-29 04:03
  • It is to prevent a class from being inherited. From Wikipedia:

    C++11 also adds the ability to prevent inheriting from classes or simply preventing overriding methods in derived classes. This is done with the special identifier final. For example:

    struct Base1 final { };
    
    struct Derived1 : Base1 { }; // ill-formed because the class Base1 
                                 // has been marked final
    
  • It is also used to mark a virtual function so as to prevent it from being overridden in the derived classes:

    struct Base2 {
        virtual void f() final;
    };
    
    struct Derived2 : Base2 {
        void f(); // ill-formed because the virtual function Base2::f has 
                  // been marked final
    };
    

Wikipedia further makes an interesting point:

Note that neither override nor final are language keywords. They are technically identifiers; they only gain special meaning when used in those specific contexts. In any other location, they can be valid identifiers.

That means, the following is allowed:

int const final = 0;     // ok
int const override = 1;  // ok
查看更多
一纸荒年 Trace。
4楼-- · 2020-01-29 04:06

What you are missing, as idljarn already mentioned in a comment is that if you are overriding a function from a base class, then you cannot possibly mark it as non-virtual:

struct base {
   virtual void f();
};
struct derived : base {
   void f() final;       // virtual as it overrides base::f
};
struct mostderived : derived {
   //void f();           // error: cannot override!
};
查看更多
倾城 Initia
5楼-- · 2020-01-29 04:07

Nothing to add to the semantic aspects of "final".

But I'd like to add to chris green's comment that "final" might become a very important compiler optimization technique in the not so distant future. Not only in the simple case he mentioned, but also for more complex real-world class hierarchies which can be "closed" by "final", thus allowing compilers to generate more efficient dispatching code than with the usual vtable approach.

One key disadvantage of vtables is that for any such virtual object (assuming 64-bits on a typical Intel CPU) the pointer alone eats up 25% (8 of 64 bytes) of a cache line. In the kind of applications I enjoy to write, this hurts very badly. (And from my experience it is the #1 argument against C++ from a purist performance point of view, i.e. by C programmers.)

In applications which require extreme performance, which is not so unusual for C++, this might indeed become awesome, not requiring to workaround this problem manually in C style or weird Template juggling.

This technique is known as Devirtualization. A term worth remembering. :-)

There is a great recent speech by Andrei Alexandrescu which pretty well explains how you can workaround such situations today and how "final" might be part of solving similar cases "automatically" in the future (discussed with listeners):

http://channel9.msdn.com/Events/GoingNative/2013/Writing-Quick-Code-in-Cpp-Quickly

查看更多
登录 后发表回答