final
specifier(since C++11)General topics | ||||||||||||||||
Flow control | ||||||||||||||||
Conditional execution statements | ||||||||||||||||
Iteration statements (loops) | ||||||||||||||||
Jump statements | ||||||||||||||||
Functions | ||||||||||||||||
Function declaration | ||||||||||||||||
Lambda function expression | ||||||||||||||||
inline specifier | ||||||||||||||||
Dynamic exception specifications(until C++17*) | ||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||
Exceptions | ||||||||||||||||
Namespaces | ||||||||||||||||
Types | ||||||||||||||||
Specifiers | ||||||||||||||||
| ||||||||||||||||
Storage duration specifiers | ||||||||||||||||
Initialization | ||||||||||||||||
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
Specifies that avirtual function cannot be overridden in a derived class, or that a class cannot bederived from.
Contents |
When applied to a member function, the identifierfinal
appears immediately after thedeclarator in the syntax of a member function declaration or a member function definition inside a class definition.
When applied to a class (including struct and union), the identifierfinal
appears at the beginning of the class definition, immediately after the name of the class, and cannot appear in a class declaration.
declaratorvirt-specifier-seq (optional)pure-specifier (optional) | (1) | ||||||||
declaratorvirt-specifier-seq (optional)function-body | (2) | ||||||||
class-keyattr (optional)class-head-nameclass-virt-specifier (optional)base-clause (optional) | (3) | (until C++26) | |||||||
class-keyattr (optional)class-head-nameclass-prop-specifier-seq (optional)base-clause (optional) | (4) | (since C++26) | |||||||
final
may appear invirt-specifier-seq immediately after the declarator, and before thepure-specifier, if used.final
may appear invirt-specifier-seq immediately after the declarator and just beforefunction-body.final
may appear asclass-virt-specifier immediately after the name of the class, just before the colon that begins thebase-clause, if used.final
may appear inclass-prop-specifier-seq, if used, but only once.In the cases(1,2),virt-specifier-seq, if used, is eitheroverride
orfinal
, orfinal override
oroverride final
. In the case(3), the only allowed value ofclass-virt-specifier, if used, isfinal
. In the case(4), theclass-prop-specifier-seq, if used, can have any number ofclass property specifiers(since C++26), but each can appear at most once.
When used in a virtual function declaration or definition,final specifier ensures that the function is virtual and specifies that it may not be overridden by derived classes. The program is ill-formed (a compile-time error is generated) otherwise.
When used in a class definition,final specifies that this class may not appear in thebase-specifier-list of another class definition (in other words, cannot be derived from). The program is ill-formed otherwise (a compile-time error is generated).final can also be used with aunion definition, in which case it has no effect (other than on the outcome ofstd::is_final)(since C++14), since unions cannot be derived from.
final is an identifier with a special meaning when used in a member function declaration or class head. In other contexts, it is not reserved and may be used to name objects and functions.
In a sequence of the following tokens:
the third tokenfinal in the sequence is always considered as a specifier instead of an identifier.
struct A;struct A final{};// OK, definition of struct A,// not value-initialization of variable final struct X{struct C{constexpr operatorint(){return5;}};struct B final: C{};// OK, definition of nested class B,// not declaration of a bit-field member final}; // Abnormal final usage. struct final final// OK, definition of a struct named `final` from which{// you cannot inherit}; // struct final final {}; // Error: redefinition of `struct final`, NOT a// definition of a variable `final` using an elaborated// type specifier `struct final` followed by an// aggregate initialization // struct override : final {}; // Error: cannot derive from final base type;// `override` in given context is a normal namevoid foo(){[[maybe_unused]] final final;// OK, declaration of a variable named `final` of type// `struct final`} struct final final;// OK, declaration of a variable named `final` of type// `struct final` using an elaborated type specifierint main(){}
struct Base{virtualvoid foo();}; struct A: Base{void foo() final;// Base::foo is overridden and A::foo is the final overridevoid bar() final;// Error: bar cannot be final as it is non-virtual}; struct B final: A// struct B is final{void foo() override;// Error: foo cannot be overridden as it is final in A}; struct C: B{};// Error: B is final
Possible output:
main.cpp:9:10: error: 'void A::bar()' marked 'final', but is not virtual 9 | void bar() final; // Error: bar cannot be final as it is non-virtual | ^~~main.cpp:14:10: error: virtual function 'virtual void B::foo()' overriding final function 14 | void foo() override; // Error: foo cannot be overridden as it is final in A | ^~~main.cpp:8:10: note: overridden function is 'virtual void A::foo()' 8 | void foo() final; // Base::foo is overridden and A::foo is the final override | ^~~main.cpp:17:8: error: cannot derive from 'final' base 'B' in derived type 'C' 17 | struct C : B // Error: B is final |
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1318 | C++11 | a class definition which hasfinal after the class name and an empty member specification list might makefinal an identifier | final is always a specifier in this case |
override specifier(C++11) | explicitly declares that a method overrides another method[edit] |
class property specifiers(C++26) | final specifier(C++11),replaceability(C++26),trivial relocatability(C++26)[edit] |