Klassendeklaration
Klassen sind benutzerdefinierte Typen, die durch einen `class-specifier` definiert werden, welcher in der decl-specifier-seq der Deklarationssyntax vorkommt.
Inhalt |
[edit] Syntax
Der Klassenspezifizierer hat 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 | - | eines von class, struct und union. Die Schlüsselwörter class und struct sind identisch, mit Ausnahme des Standard-Mitgliederzugriffs und des Standard-Basisklassenzugriffs. Wenn es union ist, führt die Deklaration einen Union-Typ ein. | ||||||||
| attr | - | (seit C++11) eine beliebige Anzahl von Attributen, kann alignas-Spezifizierer enthalten | ||||||||
| class-head-name | - | der Name der Klasse, die gerade definiert wird, optional qualifiziert | ||||||||
| class-property-specs | - | Eine Liste der folgenden Spezifizierer, jeder Spezifizierer ist in jeder Sequenz höchstens einmal erlaubt.
| ||||||||
| base-clause | - | Liste einer oder mehrerer Basisklassen und des für jede verwendete Vererbungsmodell (siehe abgeleitete Klasse) | ||||||||
| member-specification | - | Liste von Zugriffspezifizierern, Deklarationen und Definitionen von Memberobjekten und Memberfunktionen (siehe unten) |
[edit] 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 einen unvollständigen Typ. Dies ermöglicht Klassen, die sich gegenseitig referenzieren
class Vector; // forward declaration 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> // contains forward declaration of std::ostream struct MyStruct { int value; friend std::ostream& operator<<(std::ostream& os, const S& s); // definition provided in MyStruct.cpp file which uses #include <ostream> };
Wenn eine Vorwärtsdeklaration im lokalen Gültigkeitsbereich erscheint, *verdeckt* sie zuvor deklarierte Klassen, Variablen, Funktionen und alle anderen Deklarationen mit demselben Namen, die in umschließenden Gültigkeitsbereichen erscheinen mögen.
struct s { int a; }; struct s; // does nothing (s already defined in this scope) void g() { struct s; // forward declaration of a new, local struct "s" // this hides global struct s until the end of this block s* p; // pointer to local struct s struct s { char* p; }; // definitions of the local struct s }
Beachten Sie, dass ein neuer Klassenname auch durch einen elaborierten Typspezifizierer eingeführt werden kann, der als Teil einer anderen Deklaration erscheint, aber nur, wenn die Namenssuche keine zuvor deklarierte Klasse mit demselben Namen findet.
class U; namespace ns { class Y f(class T p); // declares function ns::f and declares ns::T and ns::Y class U f(); // U refers to ::U // can use pointers and references to T and Y Y* p; T* q; }
[edit] Mitgliederspezifikation
Die Mitgliederspezifikation oder der *Rumpf* 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) eine beliebige Anzahl von Attributen |
| decl-specifier-seq | - | Sequenz von Spezifizierern. Sie ist nur in den Deklarationen von Konstruktoren, Destruktoren und benutzerdefinierten Typumwandlungsfunktionen (Konvertierungsfunktionen) optional. |
| member-declarator-list | - | ähnlich einer init-declarator-list, erlaubt aber zusätzlich die Deklaration von Bitfeldern, pure-specifier, und virt-specifier (override oder final)(seit C++11) und erlaubt keine Direktinitialisierung ohne Listen-Syntax. |
Diese Deklaration kann statische und nicht-statische Datenmember und Memberfunktionen, Member-typedefs, Member-Aufzählungen und verschachtelte Klassen deklarieren. Sie kann auch eine friend-Deklaration sein.
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; // make Base's protected member d a public member of Derived using Base::Base; // inherit all bases' constructors (C++11) };
static_assert-Deklarationentemplate<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) Deduktions-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) |
[edit] Lokale Klassen
Eine Klassendeklaration kann innerhalb des Körpers einer Funktion erscheinen, in diesem Fall definiert sie eine *lokale Klasse*. Der Name einer solchen Klasse existiert nur innerhalb des Funktions-Gültigkeitsbereichs und ist von außen nicht zugänglich.
- Mitglieder einer lokalen Klasse können nur in der Definition dieser Klasse deklariert werden, mit der Ausnahme, dass Mitglieder, die verschachtelte Klassen sind, auch im nächstgelegenen umschließenden Block-Gültigkeitsbereich dieser Klasse deklariert werden können.
- Eine Klasse, die innerhalb einer lokalen Klasse verschachtelt ist, ist ebenfalls eine lokale Klasse.
- Lokale Klassen dürfen keine statischen Datenmember haben.
- Memberfunktionen einer lokalen Klasse haben keine Linkage.
- Memberfunktionen einer lokalen Klasse müssen vollständig innerhalb des Klassenkörpers definiert werden.
- Lokale Klassen mit Ausnahme von Closure-Typen(seit C++14) dürfen keine Member-Templates haben.
- Lokale Klassen dürfen keine Friend-Templates haben.
- Lokale Klassen dürfen keine Friend-Funktionen innerhalb der Klassendefinition definieren.
- Eine lokale Klasse innerhalb einer Funktion (einschließlich Memberfunktion) kann auf dieselben Namen zugreifen, auf die die umschließ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
[edit] Schlüsselwörter
[edit] 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 1693 | C++98 | Mitgliedsdeklarationen konnten nicht leer sein | leere Deklaration erlaubt |
| CWG 1930 | C++98 | member-declarator-list könnte leer sein, wenn decl-specifier-seq einen Speicherklassen-Spezifizierer oder cv-Qualifizierer enthält |
die Liste darf nicht leer sein |
| CWG 2890 | C++98 | war unklar, wo die Mitglieder verschachtelter Klassen deklariert werden können | wurde klargestellt |
[edit] Siehe auch
| C-Dokumentation für Struct-Deklaration
|