Declarations
Deklarationen sind die Art und Weise, wie Namen in das C++-Programm eingeführt (oder wieder eingeführt) werden. Nicht alle Deklarationen deklarieren tatsächlich etwas, und jede Art von Entität wird unterschiedlich deklariert. Definitionen sind Deklarationen, die ausreichen, um die durch den Namen identifizierte Entität zu verwenden.
Eine Deklaration ist eines der folgenden Elemente:
- Funktionsdefinition
- Template-Deklaration (einschließlich Partielle Template-Spezialisierung )
- Explizite Template-Instanziierung
- Explizite Template-Spezialisierung
- Namespace-Definition
- Linkage-Spezifikation
|
(seit C++11) |
-
Leere Deklaration (
;) - Eine Funktionsdeklaration ohne decl-specifier-seq :
attr
(optional)
declarator
;
|
|||||||||
| attr | - | (since C++11) Folge beliebig vieler attributes |
| declarator | - | ein Funktionsdeklarator |
- Diese Deklaration muss einen Konstruktor, Destruktor oder eine benutzerdefinierte Konvertierungsfunktion deklarieren. Sie kann nur als Teil einer Template-Deklaration , expliziten Spezialisierung oder expliziten Instanziierung verwendet werden.
- block-declaration (eine Deklaration, die innerhalb eines Blocks erscheinen kann), die wiederum eine der folgenden sein kann:
| (seit C++11) |
| (seit C++20) | |
|
(seit C++11) |
-
- einfache Deklaration
Inhaltsverzeichnis
Einfache DeklarationEine einfache Deklaration ist eine Anweisung, die einen oder mehrere Bezeichner (typischerweise Variablen) einführt, erstellt und optional initialisiert.
1) Ein Deklarator mit einem Initialisierer.
2) Ein Deklarator ohne Initialisierer.
SpezifiziererDeklarationsspezifizierer ( decl-specifier-seq ) ist eine Sequenz der folgenden, durch Leerzeichen getrennten Spezifizierer in beliebiger Reihenfolge:
Attribute können in decl-specifier-seq erscheinen, in welchem Fall sie auf den durch die vorhergehenden Spezifizierer bestimmten Typ angewendet werden. Wiederholungen jeglicher Spezifizierer in einer decl-specifier-seq , wie const static const oder virtual inline virtual sind Fehler , außer dass long zweimal auftreten darf (seit C++11) . DeklaratorenJeder init-declarator in einer init-declarator-list S D1, D2, D3 ; wird so verarbeitet, als wäre es eine eigenständige Deklaration mit denselben Spezifizierern: S D1 ; S D2 ; S D3 ; . Jeder Deklarator führt genau ein Objekt, eine Referenz, eine Funktion oder (für typedef-Deklarationen) einen Typalias ein, dessen Typ durch die decl-specifier-seq bereitgestellt und optional durch Operatoren wie & (Referenz auf) oder [ ] (Array von) oder ( ) (Funktion zurückgebend) im Deklarator modifiziert wird. Diese Operatoren können rekursiv angewendet werden, wie unten gezeigt. Ein Deklarator ist einer der folgenden:
1)
Der
Name
der deklariert wird.
2)
Ein Deklarator, der einen
qualified identifier
(
qualified-id
) verwendet, definiert oder deklariert erneut ein zuvor deklariertes
namespace member
oder
class member
.
4)
Pointer-Deklarator
: die Deklaration
S
*
D
;
deklariert
D
als einen Zeiger auf den durch
Deklarator-Spezifizierer-Sequenz
S
bestimmten Typ.
5)
Deklaration eines Zeigers auf Mitglied
: die Deklaration
S C
::
*
D
;
deklariert
D
als einen Zeiger auf ein Mitglied von
C
vom Typ, bestimmt durch
Deklarationsspezifizierer-Sequenz
S
.
Verschachtelter-Namen-Spezifizierer
ist eine
Sequenz von Namen und Bereichsauflösungsoperatoren
::
6)
Lvalue-Referenzdeklarator
: die Deklaration
S
&
D
;
deklariert
D
als eine Lvalue-Referenz auf den durch
decl-specifier-seq
S
bestimmten Typ.
7)
Rvalue-Referenzdeklarator
: die Deklaration
S
&&
D
;
deklariert
D
als eine Rvalue-Referenz auf den durch
Deklarator-Spezifizierer-Sequenz
S
bestimmten Typ.
8)
Array-Deklarator
.
noptr-declarator
jeder gültige Deklarator, aber wenn er mit *, & oder && beginnt, muss er in Klammern eingeschlossen werden.
9)
Funktionsdeklarator
.
noptr-declarator
jeder gültige Deklarator, aber wenn er mit *, & oder && beginnt, muss er in Klammern eingeschlossen sein.
Er kann mit dem optionalen nachgestellten Rückgabetyp enden.
(seit C++11)
10)
Geklammerter Deklarator.
cv ist eine Sequenz von const- und volatile Qualifizierern, wobei jeder Qualifizierer höchstens einmal in der Sequenz vorkommen darf.
HinweiseWenn eine block-declaration innerhalb eines Blocks erscheint und ein durch eine Deklaration eingeführter Bezeichner zuvor in einem äußeren Block deklariert wurde, wird die äußere Deklaration für den Rest des Blocks verborgen. Wenn eine Deklaration eine Variable mit automatischer Speicherdauer einführt, wird sie initialisiert, wenn ihre Deklarationsanweisung ausgeführt wird. Alle automatischen Variablen, die in einem Block deklariert werden, werden beim Verlassen des Blocks zerstört (unabhängig davon, wie der Block verlassen wird: via exception , goto , oder durch Erreichen seines Endes), in umgekehrter Reihenfolge ihrer Initialisierung. BeispielHinweis: Dieses Beispiel demonstriert, wie einige komplexe Deklarationen gemäß der Sprachgrammatik geparst werden. Andere bekannte Merkhilfen sind: die Spiralregel , das Lesen von innen nach außen , und Deklaration spiegelt Verwendung . Es gibt auch einen automatisierten Parser unter https://cdecl.org .
Diesen Code ausführen
#include <type_traits> struct S { int member; // decl-specifier-seq is "int" // declarator is "member" { obj, *pObj(&obj); // decl-specifier-seq is "struct S { int member; }" // declarator "obj" declares an object of type S // declarator "*pObj" declares a pointer to S, // and initializer "(&obj)" initializes it int i = 1, *p = nullptr, f(), (*pf)(double); // decl-specifier-seq is "int" // declarator "i" declares a variable of type int, // and initializer "= 1" initializes it // declarator "*p" declares a variable of type int*, // and initializer "= nullptr" initializes it // declarator "f()" declares (but doesn't define) // a function taking no arguments and returning int // declarator "(*pf)(double)" declares a pointer to function // taking double and returning int int (*(*var1)(double))[3] = nullptr; // decl-specifier-seq is "int" // declarator is "(*(*var1)(double))[3]" // initializer is "= nullptr" // 1. declarator "(*(*var1)(double))[3]" is an array declarator: // Type declared is: "(*(*var1)(double))" array of 3 elements // 2. declarator "(*(*var1)(double))" is a pointer declarator: // Type declared is: "(*var1)(double)" pointer to array of 3 elements // 3. declarator "(*var1)(double)" is a function declarator: // Type declared is: "(*var1)" function taking "(double)", // returning pointer to array of 3 elements. // 4. declarator "(*var1)" is a pointer declarator: // Type declared is: "var1" pointer to function taking "(double)", // returning pointer to array of 3 elements. // 5. declarator "var1" is an identifier. // This declaration declares the object var1 of type "pointer to function // taking double and returning pointer to array of 3 elements of type int" // The initializer "= nullptr" provides the initial value of this pointer. // C++11 alternative syntax: auto (*var2)(double) -> int (*)[3] = nullptr; // decl-specifier-seq is "auto" // declarator is "(*var2)(double) -> int (*)[3]" // initializer is "= nullptr" // 1. declarator "(*var2)(double) -> int (*)[3]" is a function declarator: // Type declared is: "(*var2)" function taking "(double)", returning "int (*)[3]" // ... int main() { static_assert(std::is_same_v<decltype(var1), decltype(var2)>); } FehlerberichteDie folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
Siehe auch
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||