final
specifier
(since C++11)
Spezifiziert, dass eine virtual function nicht in einer abgeleiteten Klasse überschrieben werden kann, oder dass eine Klasse nicht derived from werden kann.
Inhaltsverzeichnis |
Syntax
Wenn auf eine Memberfunktion angewendet wird, erscheint der Bezeichner
final
unmittelbar 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, unmittelbar 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) Funktionskörper | (2) | ||||||||
| Klassen-Schlüssel attr (optional) Klassenkopfname class-virt-specifier (optional) Basisklausel (optional) | (3) | (bis C++26) | |||||||
| Klassen-Schlüssel attr (optional) Klassenkopfname class-prop-specifier-seq (optional) Basisklausel (optional) | (4) | (seit C++26) | |||||||
final
in der
virt-specifier-seq
unmittelbar nach dem Deklarator und vor dem
pure-specifier
erscheinen, falls verwendet.
final
kann in
virt-specifier-seq
unmittelbar nach dem Deklarator und direkt vor
function-body
erscheinen.
final
als
class-virt-specifier
unmittelbar nach dem Klassennamen erscheinen, direkt vor dem Doppelpunkt, der den
base-clause
einleitet, falls verwendet.
final
in der
class-prop-specifier-seq
erscheinen, falls verwendet, jedoch nur einmal.
In den Fällen
(1,2)
ist die
virt-specifier-seq
, falls verwendet, entweder
override
oder
final
, oder
final override
oder
override final
. Im Fall
(3)
ist der einzige zulässige Wert von
class-virt-specifier
, falls verwendet,
final
. Im Fall
(4)
kann die
class-prop-specifier-seq
, falls verwendet, beliebig viele
class property specifiers
enthalten
(seit C++26)
, aber jeder darf höchstens einmal vorkommen.
Erklärung
Wenn es in einer Deklaration oder Definition einer virtuellen Funktion verwendet wird, final Spezifizierer stellt sicher, dass die Funktion virtuell ist und spezifiziert, dass sie von abgeleiteten Klassen nicht überschrieben werden darf. Andernfalls ist das Programm fehlerhaft (es wird ein Kompilierzeitfehler generiert).
Wenn in einer Klassendefinition verwendet, final spezifiziert, dass diese Klasse nicht in der base-specifier-list einer anderen Klassendefinition erscheinen darf (mit anderen Worten, sie kann nicht abgeleitet werden). Andernfalls ist das Programm fehlerhaft (es wird ein Compile-Time-Fehler generiert). final kann auch mit einer union -Definition verwendet werden, in welchem Fall es keine Auswirkung hat (außer auf das Ergebnis von std::is_final ) (seit C++14) , da Unions nicht abgeleitet werden können.
final ist ein Bezeichner mit einer besonderen Bedeutung, wenn er in einer Member-Funktionsdeklaration oder einem Klassenkopf verwendet wird. In anderen Kontexten ist er nicht reserviert und kann zur Benennung von Objekten und Funktionen verwendet werden.
Hinweis
In einer Folge der folgenden Tokens:
- einer von class , struct und union
- ein möglicherweise qualifizierter Bezeichner
- final
- einer von : und {
das dritte Token final in der Sequenz wird immer als Spezifizierer anstelle eines Identifikators betrachtet.
struct A; struct A final {}; // OK, Definition von struct A, // keine Wertinitialisierung der Variable final struct X { struct C { constexpr operator int() { return 5; } }; struct B final : C{}; // OK, Definition der geschachtelten Klasse B, // keine Deklaration eines Bitfeld-Members final }; // Ungewöhnliche final-Verwendung. struct final final // OK, Definition einer struct namens `final`, von der { // man nicht erben kann }; // struct final final {}; // Fehler: Neudefinition von `struct final`, KEINE // Definition einer Variable `final` mit einem erweiterten // Typspezifizierer `struct final` gefolgt von einer // Aggregatinitialisierung // struct override : final {}; // Fehler: Kann nicht von finaler Basisklasse ableiten; // `override` ist in diesem Kontext ein normaler Name void foo() { [[maybe_unused]] final final; // OK, Deklaration einer Variable namens `final` vom Typ // `struct final` } struct final final; // OK, Deklaration einer Variable namens `final` vom Typ // `struct final` mit einem erweiterten Typspezifizierer int main() { }
Schlüsselwörter
Beispiel
struct Base { virtual void foo(); }; struct A : Base { void foo() final; // Base::foo wird überschrieben und A::foo ist der finale Override void bar() final; // Fehler: bar kann nicht final sein, da es nicht virtuell ist }; struct B final : A // struct B ist final { void foo() override; // Fehler: foo kann nicht überschrieben werden, da es in A final ist }; struct C : B {}; // Fehler: B ist final
Mögliche Ausgabe:
main.cpp:9:10: error: 'void A::bar()' marked 'final', but is not virtual
9 | void bar() final; // Fehler: bar kann nicht final sein, da es nicht virtuell ist
| ^~~
main.cpp:14:10: error: virtual function 'virtual void B::foo()' overriding final function
14 | void foo() override; // Fehler: foo kann nicht überschrieben werden, da es in A final ist
| ^~~
main.cpp:8:10: note: overridden function is 'virtual void A::foo()'
8 | void foo() final; // Base::foo wird überschrieben und A::foo ist der finale Override
| ^~~
main.cpp:17:8: error: cannot derive from 'final' base 'B' in derived type 'C'
17 | struct C : B // Fehler: B ist final
|
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]
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| CWG 1318 | C++11 |
eine Klassendefinition, die
final
nach dem Klassennamen und eine
leere Mitgliederspezifikationsliste hat, könnte final zu einem Bezeichner machen |
final
ist in diesem Fall immer ein
Spezifizierer |
Siehe auch
override
Spezifizierer
(C++11)
|
deklariert explizit, dass eine Methode eine andere Methode überschreibt |
| Klassen-Eigenschafts-Spezifizierer (C++26) | final Spezifizierer (C++11) , Ersetzbarkeit (C++26) , triviale Relokalisierbarkeit (C++26) |