Elaborated type specifier
Ausgeführte Typspezifizierer können verwendet werden, um auf einen zuvor deklarierten Klassennamen (class, struct oder union) oder einen zuvor deklarierten Enum-Namen zu verweisen, selbst wenn der Name durch eine Nicht-Typ-Deklaration verborgen wurde . Sie können auch verwendet werden, um neue Klassennamen zu deklarieren.
Inhaltsverzeichnis |
Syntax
| class-key class-name | (1) | ||||||||
enum
enum-name
|
(2) | ||||||||
class-key
attr
(optional)
identifier
;
|
(3) | ||||||||
| class-key | - | einer von class , struct , union |
| class-name | - | der Name eines zuvor deklarierten Klassentyps, optional qualifiziert , oder ein Bezeichner, der nicht zuvor als Typname deklariert wurde |
| enum-name | - | der Name eines zuvor deklarierten Aufzählungstyps, optional qualifiziert |
| attr | - | (seit C++11) beliebig viele attributes |
Opaque enum declaration ähnelt der Form (3) , aber der Enum-Typ ist nach einer Opaque enum declaration ein vollständiger Typ.
Erklärung
Form (3) ist ein Sonderfall eines elaborated type specifier, üblicherweise bezeichnet als forward declaration von Klassen. Für die Beschreibung von Form (3) siehe Forward declaration . Die folgenden Ausführungen gelten nur für Form (1) und (2) .
Der class-name oder enum-name im elaborated type specifier kann entweder ein einfacher Bezeichner oder eine qualified-id sein. Der Name wird mittels unqualified name lookup oder qualified name lookup gesucht, abhängig von deren Erscheinungsform. In beiden Fällen werden jedoch keine Nicht-Typ-Namen berücksichtigt.
class T { public: class U; private: int U; }; int main() { int T; T t; // Fehler: Die lokale Variable T wird gefunden class T t; // OK: findet ::T, die lokale Variable T wird ignoriert T::U* u; // Fehler: Suche nach T::U findet das private Datenelement class T::U* u; // OK: Das Datenelement wird ignoriert }
Wenn die Namenssuche keinen zuvor deklarierten Typnamen findet, der elaborated-type-specifier durch
class
,
struct
, oder
union
eingeleitet wird (d.h. nicht durch
enum
), und
class-name
ein unqualifizierter Bezeichner ist, dann ist der elaborated-type-specifier eine Klassendeklaration des class-name, und der Zielbereich ist der nächstgelegene umschließende Namensraum oder Blockbereich.
template<typename T> struct Node { struct Node* Next; // OK: Suche nach Node findet den injizierten Klassennamen struct Data* Data; // OK: deklariert Typ Data im globalen Gültigkeitsbereich // und deklariert auch das Datenelement Data friend class ::List; // Fehler: qualifizierter Name kann nicht eingeführt werden enum Kind* kind; // Fehler: Enum kann nicht eingeführt werden }; Data* p; // OK: struct Data wurde deklariert
Wenn der Name auf einen typedef-Namen , einen Typ-Alias , einen Template-Typparameter oder eine Alias-Template-Spezialisierung verweist, ist das Programm fehlerhaft; andernfalls führt der elaborierte Typspezifizierer den Namen in die Deklaration auf die gleiche Weise ein, wie ein einfacher Typspezifizierer seinen Typnamen einführt.
template<typename T> class Node { friend class T; // Fehler: Typparameter kann nicht in einem spezifizierten Typbezeichner vorkommen; // Hinweis: Ähnliche Deklaration `friend T;` ist korrekt. }; class A {}; enum b { f, t }; int main() { class A a; // OK: Entspricht 'A a;' enum b flag; // OK: Entspricht 'b flag;' }
Das
class-key
oder
enum
Schlüsselwort, das im elaborated-type-specifier vorhanden ist, muss in der Art mit der Deklaration übereinstimmen, auf die der Name im elaborated-type-specifier verweist.
-
das
enumSchlüsselwort muss verwendet werden, um sich auf einen Aufzählungstyp (ob scoped oder unscoped) zu beziehen -
das
unionclass-key muss verwendet werden, um sich auf eine Union zu beziehen -
entweder das
classoderstructclass-key muss verwendet werden, um sich auf einen Nicht-Union-Klassentyp zu beziehen (die Schlüsselwörterclassundstructsind hier austauschbar).
enum class E { a, b }; enum E x = E::a; // OK enum class E y = E::b; // Fehler: 'enum class' kann keinen elaborated type specifier einführen struct A {}; class A a; // OK
Wenn es als
Template-Argument
verwendet wird,
class
T
ist ein Typ-Template-Parameter namens
T
, kein unbenannter konstanter Parameter, dessen Typ
T
durch einen erweiterten Typspezifizierer eingeführt wird.
Schlüsselwörter
Referenzen
- C++23-Standard (ISO/IEC 14882:2024):
-
- 6.5.6 Elaborated type specifiers [basic.lookup.elab]
-
- 9.2.9.4 Elaborated type specifiers [dcl.type.elab]
- C++20-Standard (ISO/IEC 14882:2020):
-
- 6.5.4 Elaborated type specifiers [basic.lookup.elab]
-
- 9.2.8.3 Elaborated type specifiers [dcl.type.elab]
- C++17-Standard (ISO/IEC 14882:2017):
-
- 6.4.4 Elaborierte Typspezifizierer [basic.lookup.elab]
-
- 10.1.7.3 Elaborierte Typspezifizierer [dcl.type.elab]
- C++14-Standard (ISO/IEC 14882:2014):
-
- 3.4.4 Elaborated type specifiers [basic.lookup.elab]
-
- 7.1.6.3 Elaborated type specifiers [dcl.type.elab]
- C++11-Standard (ISO/IEC 14882:2011):
-
- 3.4.4 Elaborated type specifiers [basic.lookup.elab]
-
- 7.1.6.3 Elaborated type specifiers [dcl.type.elab]
- C++98 Standard (ISO/IEC 14882:1998):
-
- 3.4.4 Elaborated type specifiers [basic.lookup.elab]
-
- 7.1.5.3 Elaborated type specifiers [dcl.type.elab]
|
Dieser Abschnitt ist unvollständig
Grund: wahrscheinlich den Großteil von 9.1[class.name]/2-3 aus cpp/language/class herausziehen |