What is the purpose of the "final" keyword in C++11 for functions?
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?
Solution 1:
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!
};
Solution 2:
-
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
norfinal
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
Solution 3:
"final" also allows a compiler optimization to bypass the indirect call:
class IAbstract
{
public:
virtual void DoSomething() = 0;
};
class CDerived : public IAbstract
{
void DoSomething() final { m_x = 1 ; }
void Blah( void ) { DoSomething(); }
};
with "final", the compiler can call CDerived::DoSomething()
directly from within Blah()
, or even inline. Without it, it has to generate an indirect call inside of Blah()
because Blah()
could be called inside a derived class which has overridden DoSomething()
.