Class declaration
Klassen sind benutzerdefinierte Typen, definiert durch einen Klassen-Spezifizierer, der in der decl-specifier-seq der Deklarations -Syntax erscheint.
Inhaltsverzeichnis |
Syntax
Die Klassenspezifikation hat die folgende Syntax:
class-key
attr
(optional)
class-head-name
class-property-specs
(optional)
base-clause
(optional)
{
member-specification
}
|
(1) | ||||||||
class-key
attr
(optional)
base-clause
(optional)
{
member-specification
}
|
(2) | ||||||||
| class-key | - | einer von class , struct und union . Die Schlüsselwörter class und struct sind identisch, außer für den Standard- Mitgliedszugriff und den Standard- Basisklassenzugriff . Wenn es union ist, führt die Deklaration einen Union-Typ ein. | ||||||||
| attr | - |
(seit C++11)
beliebig viele
Attribute
, kann
alignas
Spezifizierer enthalten
|
||||||||
| class-head-name | - | der Name der zu definierenden Klasse, optional qualifiziert | ||||||||
| class-property-specs | - |
Eine Liste der folgenden Spezifizierer, jeder Spezifizierer ist in jeder Sequenz höchstens einmal erlaubt.
|
||||||||
| base-clause | - | Liste von einer oder mehreren Basisklassen und dem für jede verwendeten Vererbungsmodell (siehe abgeleitete Klasse ) | ||||||||
| member-specification | - | Liste von Zugriffsspezifizierern, Mitgliedsobjekt- und Mitgliedsfunktionsdeklarationen und -definitionen ( siehe unten ) |
Vorwärtsdeklaration
Eine Deklaration der folgenden Form
class-key
attr
identifier
;
|
|||||||||
Deklariert einen Klassentyp, der später in diesem Gültigkeitsbereich definiert wird. Bis die Definition erscheint, hat dieser Klassenname unvollständigen Typ . Dies erlaubt Klassen, die sich gegenseitig referenzieren:
class Vector; // Vorwärtsdeklaration class Matrix { // ... friend Vector operator*(const Matrix&, const Vector&); }; class Vector { // ... friend Vector operator*(const Matrix&, const Vector&); };
und wenn eine bestimmte Quelldatei nur Zeiger und Referenzen auf die Klasse verwendet, ermöglicht dies die Reduzierung von #include Abhängigkeiten:
// In MyStruct.h #include <iosfwd> // enthält Vorwärtsdeklaration von std::ostream struct MyStruct { int value; friend std::ostream& operator<<(std::ostream& os, const S& s); // Definition bereitgestellt in MyStruct.cpp Datei, die #include <ostream> verwendet };
Wenn eine Vorwärtsdeklaration im lokalen Gültigkeitsbereich erscheint, verdeckt sie die zuvor deklarierte Klasse, Variable, Funktion und alle anderen Deklarationen desselben Namens, die in umschließenden Gültigkeitsbereichen erscheinen können:
struct s { int a; }; struct s; // tut nichts (s ist bereits in diesem Gültigkeitsbereich definiert) void g() { struct s; // Vorwärtsdeklaration einer neuen, lokalen Struktur "s" // dies verdeckt die globale Struktur s bis zum Ende dieses Blocks s* p; // Zeiger auf lokale Struktur s struct s { char* p; }; // Definition der lokalen Struktur s }
Beachten Sie, dass ein neuer Klassenname auch durch einen elaborated type specifier eingeführt werden kann, der als Teil einer anderen Deklaration erscheint, aber nur wenn name lookup keine zuvor deklarierte Klasse mit demselben Namen finden kann.
class U; namespace ns { class Y f(class T p); // deklariert Funktion ns::f und deklariert ns::T und ns::Y class U f(); // U bezieht sich auf ::U // kann Zeiger und Referenzen auf T und Y verwenden Y* p; T* q; }
Memberspezifikation
Die Memberspezifikation, oder der Body einer Klassendefinition, ist eine in geschweifte Klammern eingeschlossene Sequenz einer beliebigen Anzahl der folgenden Elemente:
attr
(optional)
decl-specifier-seq
(optional)
member-declarator-list
(optional)
;
|
|||||||||
| attr | - | (seit C++11) beliebige Anzahl von Attributen |
| decl-specifier-seq | - | Sequenz von Spezifizierern . Nur optional in den Deklarationen von Konstruktoren, Destruktoren und benutzerdefinierten Typumwandlungsfunktionen |
| member-declarator-list | - |
ähnlich einer
Init-Deklarator-Liste
, erlaubt aber zusätzlich
Bitfeld-Deklarationen
,
Pure-Spezifizierer
und Virt-Spezifizierer (
override
oder
final
)
(seit C++11)
und erlaubt keine
direkte Nicht-Listen-Initialisierungssyntax
.
|
Diese Deklaration kann statische und nicht-statische Datenelemente und Elementfunktionen , Element- Typdefinitionen , Element- Aufzählungen sowie geschachtelte Klassen deklarieren. Es kann sich auch um eine Friend-Deklaration handeln.
class S { int d1; // non-static data member int a[10] = {1, 2}; // non-static data member with initializer (C++11) static const int d2 = 1; // static data member with initializer virtual void f1(int) = 0; // pure virtual member function std::string d3, *d4, f2(int); // two data members and a member function enum { NORTH, SOUTH, EAST, WEST }; struct NestedS { std::string s; } d5, *d6; typedef NestedS value_type, *pointer_type; };
class M { std::size_t C; std::vector<int> data; public: M(std::size_t R, std::size_t C) : C(C), data(R*C) {} // constructor definition int operator()(std::size_t r, std::size_t c) const // member function definition { return data[r * C + c]; } int& operator()(std::size_t r, std::size_t c) // another member function definition { return data[r * C + c]; } };
public:
,
protected:
, und
private:
class S { public: S(); // public constructor S(const S&); // public copy constructor virtual ~S(); // public virtual destructor private: int* ptr; // private data member };
class Base { protected: int d; }; class Derived : public Base { public: using Base::d; // mache Bases geschütztes Mitglied d zu einem öffentlichen Mitglied von Derived using Base::Base; // erbe alle Konstruktoren der Basisklassen (C++11) };
static_assert
Deklarationen:
template<typename T> struct Foo { static_assert(std::is_floating_point<T>::value, "Foo<T>: T must be floating point"); };
struct S { template<typename T> void f(T&& n); template<class CharT> struct NestedS { std::basic_string<CharT> s; }; };
| (seit C++11) |
|
8)
Deduction-Guides
von Member-Klassen-Templates:
struct S { template<class CharT> struct NestedS { std::basic_string<CharT> s; }; template<class CharT> NestedS(std::basic_string<CharT>) -> NestedS<CharT>; }; |
(seit C++17) |
|
9)
Using-enum-Deklarationen
:
enum class color { red, orange, yellow }; struct highlight { using enum color; }; |
(seit C++20) |
Lokale Klassen
Eine Klassendeklaration kann im Rumpf einer Funktion erscheinen, in welchem Fall sie eine lokale Klasse definiert. Der Name einer solchen Klasse existiert nur innerhalb des Funktionsbereichs und ist von außen nicht zugänglich.
- Mitglieder einer lokalen Klasse können nur in der Definition dieser Klasse deklariert werden, außer dass Mitglieder, die geschachtelte Klassen sind, auch im nächstgelegenen einschließenden Blockgültigkeitsbereich dieser Klasse deklariert werden können.
- Eine innerhalb einer lokalen Klasse geschachtelte Klasse ist ebenfalls eine lokale Klasse.
- Eine lokale Klasse kann keine statischen Datenelemente haben.
- Mitgliedsfunktionen einer lokalen Klasse haben keine Verknüpfung.
- Mitgliedsfunktionen einer lokalen Klasse müssen vollständig innerhalb des Klassenkörpers definiert werden.
- Lokale Klassen außer Closure-Typen (seit C++14) können keine Mitgliedstemplates haben.
- Lokale Klassen können keine Friend-Templates haben.
- Lokale Klassen können keine Friend-Funktionen innerhalb der Klassendefinition definieren.
- Eine lokale Klasse innerhalb einer Funktion (einschließlich Mitgliedsfunktion) kann auf dieselben Namen zugreifen, auf die die einschließende Funktion zugreifen kann.
|
(bis C++11) |
#include <algorithm> #include <iostream> #include <vector> int main() { std::vector<int> v{1, 2, 3}; struct Local { bool operator()(int n, int m) { return n > m; } }; std::sort(v.begin(), v.end(), Local()); // since C++11 for (int n : v) std::cout << n << ' '; std::cout << '\n'; }
Ausgabe:
3 2 1
Schlüsselwörter
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 1693 | C++98 | Member-Deklarationen konnten nicht leer sein | Leere Deklaration erlaubt |
| CWG 1930 | C++98 |
member-declarator-list
konnte leer sein, wenn
decl-specifier-seq
eine Speicherklassenspezifikation oder CV-Qualifizierung enthält |
Die Liste darf nicht leer sein |
| CWG 2890 | C++98 | Es war unklar, wo die Member verschachtelter Klassen deklariert werden können | Klarstellung vorgenommen |
Siehe auch
|
C-Dokumentation
für
Struct-Deklaration
|