final-Spezifizierer (seit C++11)
Gibt an, dass eine virtuelle Funktion in einer abgeleiteten Klasse nicht überschrieben werden kann oder dass von einer Klasse nicht abgeleitet werden kann.
Inhalt |
[bearbeiten] Syntax
Wenn auf eine Memberfunktion angewendet, erscheint der Bezeichner final direkt nach dem Deklarator in der Syntax einer Memberfunktionsdeklaration oder einer Memberfunktionsdefinition innerhalb einer Klassendefinition.
Wenn auf eine Klasse (einschließlich struct und union) angewendet, erscheint der Bezeichner final am Anfang der Klassendefinition, direkt nach dem Namen der Klasse, und kann nicht in einer Klassendeklaration erscheinen.
| deklarator virt-specifier-seq (optional) pure-specifier (optional) | (1) | ||||||||
| deklarator virt-specifier-seq (optional) function-body | (2) | ||||||||
| class-key attr (optional) class-head-name class-virt-specifier (optional) base-clause (optional) | (3) | (bis C++26) | |||||||
| class-key attr (optional) class-head-name class-prop-specifier-seq (optional) base-clause (optional) | (4) | (seit C++26) | |||||||
final im virt-specifier-seq unmittelbar nach dem Deklarator und vor dem pure-specifier, falls verwendet, stehen.final im virt-specifier-seq unmittelbar nach dem Deklarator und direkt vor function-body stehen.final als class-virt-specifier unmittelbar nach dem Klassennamen und direkt vor dem Doppelpunkt stehen, der die base-clause einleitet, falls verwendet.final im class-prop-specifier-seq, falls verwendet, vorkommen, aber nur einmal.In den Fällen (1,2) ist virt-specifier-seq, falls verwendet, entweder override oder final, oder final override oder override final. Im Fall (3) ist der einzig erlaubte Wert von class-virt-specifier, falls verwendet, final. Im Fall (4) kann class-prop-specifier-seq, falls verwendet, eine beliebige Anzahl von Klasseneigenschaftsspezifizierern (seit C++26) haben, aber jeder kann höchstens einmal vorkommen.
[bearbeiten] Erklärung
Wenn der final-Spezifizierer in einer Deklaration oder Definition einer virtuellen Funktion verwendet wird, stellt er sicher, dass die Funktion virtuell ist, und gibt an, dass sie von abgeleiteten Klassen nicht überschrieben werden darf. Andernfalls ist das Programm fehlerhaft (ein Kompilierungsfehler wird generiert).
Wenn der final-Spezifizierer in einer Klassendefinition verwendet wird, gibt er an, dass diese Klasse nicht in der base-specifier-list einer anderen Klassendefinition vorkommen darf (d. h. von ihr kann nicht abgeleitet werden). Andernfalls ist das Programm fehlerhaft (ein Kompilierungsfehler wird generiert). final kann auch mit einer union-Definition verwendet werden, in diesem Fall hat es keine Auswirkung (außer auf das Ergebnis von std::is_final)(seit C++14), da von Unions nicht abgeleitet werden kann.
final ist ein Bezeichner mit besonderer Bedeutung, wenn er in einer Memberfunktionsdeklaration oder einem Klassenheader verwendet wird. In anderen Kontexten ist er nicht reserviert und kann zur Benennung von Objekten und Funktionen verwendet werden.
[bearbeiten] Hinweis
In einer Sequenz der folgenden Tokens
- eines von class, struct und union
- ein möglicherweise qualifizierter Bezeichner
- final
- eines von : und {
wird das dritte Token final in der Sequenz immer als Spezifizierer und nicht als Bezeichner betrachtet.
struct A; struct A final {}; // OK, definition of struct A, // not value-initialization of variable final struct X { struct C { constexpr operator int() { return 5; } }; 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 name void 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 specifier int main() { }
[bearbeiten] Schlüsselwörter
[bearbeiten] Beispiel
struct Base { virtual void foo(); }; struct A : Base { void foo() final; // Base::foo is overridden and A::foo is the final override void 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
Mögliche Ausgabe
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
|[bearbeiten] Referenzen
- C++23 Standard (ISO/IEC 14882:2024)
- 11 Klassen [class]
- 11.7.3 Virtuelle Funktionen [class.virtual]
- C++20 Standard (ISO/IEC 14882:2020)
- 11 Klassen [class]
- 11.7.2 Virtuelle Funktionen [class.virtual]
- C++17 Standard (ISO/IEC 14882:2017)
- 12 Klassen [class]
- 13.3 Virtuelle Funktionen [class.virtual]
- C++14 Standard (ISO/IEC 14882:2014)
- 9 Klassen [class]
- 10.3 Virtuelle Funktionen [class.virtual]
- C++11 Standard (ISO/IEC 14882:2011)
- 9 Klassen [class]
- 10.3 Virtuelle Funktionen [class.virtual]
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 1318 | C++11 | eine Klassendefinition, die final nach dem Klassennamen und einer leeren Member-Spezifikationsliste hat, könnte final zu einem Bezeichner machen |
final ist in diesem Fall immer ein Spezifizierer |
[bearbeiten] Siehe auch
override-Spezifizierer (C++11) |
deklariert explizit, dass eine Methode eine andere Methode überschreibt |
| Klasseneigenschaftsspezifizierer (C++26) | final-Spezifizierer (C++11), Ersetzbarkeit (C++26), Triviale Relokationsfähigkeit (C++26) |