Namensräume
Varianten
Aktionen

Verschachtelte Klassen

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Eine Deklaration einer Klasse/Struktur oder Union kann innerhalb einer anderen Klasse erscheinen. Eine solche Deklaration deklariert eine verschachtelte Klasse.

[bearbeiten] Erklärung

Der Name der verschachtelten Klasse existiert im Geltungsbereich der umschließenden Klasse, und die Namensauflösung von einer Memberfunktion einer verschachtelten Klasse besucht den Geltungsbereich der umschließenden Klasse, nachdem der Geltungsbereich der verschachtelten Klasse untersucht wurde. Wie jeder Member seiner umschließenden Klasse hat die verschachtelte Klasse Zugriff auf alle Namen (private, protected usw.), auf die die umschließende Klasse Zugriff hat, ist aber ansonsten unabhängig und hat keinen besonderen Zugriff auf den this-Zeiger der umschließenden Klasse. Deklarationen in einer verschachtelten Klasse können beliebige Member der umschließenden Klasse verwenden, gemäß den üblichen Nutzungsregeln für die nicht-statischen Member.

int x, y; // globals
class enclose // enclosing class
{
    // note: private members
    int x;
    static int s;
public:
    struct inner // nested class
    {
        void f(int i)
        {
            x = i; // Error: can't write to non-static enclose::x without instance
            int a = sizeof x; // Error until C++11,
                              // OK in C++11: operand of sizeof is unevaluated,
                              // this use of the non-static enclose::x is allowed.
            s = i;   // OK: can assign to the static enclose::s
            ::x = i; // OK: can assign to global x
            y = i;   // OK: can assign to global y
        }
 
        void g(enclose* p, int i)
        {
            p->x = i; // OK: assign to enclose::x
        }
    };
};

Friend-Funktionen, die innerhalb einer verschachtelten Klasse definiert sind, haben keinen besonderen Zugriff auf die Member der umschließenden Klasse, auch wenn die Auflösung aus dem Körper einer Memberfunktion, die innerhalb einer verschachtelten Klasse definiert ist, die privaten Member der umschließenden Klasse finden kann.

Definitionen von Membern einer verschachtelten Klasse außerhalb der Klasse erscheinen im Namespace der umschließenden Klasse

struct enclose
{
    struct inner
    {
        static int x;
        void f(int i);
    };
};
 
int enclose::inner::x = 1;       // definition
void enclose::inner::f(int i) {} // definition

Verschachtelte Klassen können vorwärts deklariert und später definiert werden, entweder innerhalb desselben umschließenden Klassenkörpers oder außerhalb davon

class enclose
{
    class nested1;    // forward declaration
    class nested2;    // forward declaration
    class nested1 {}; // definition of nested class
};
 
class enclose::nested2 {}; // definition of nested class

Deklarationen von verschachtelten Klassen unterliegen Mitgliedszugriffsregeln. Eine private Mitgliedsklasse kann außerhalb des Geltungsbereichs der umschließenden Klasse nicht benannt werden, obwohl Objekte dieser Klasse manipuliert werden können.

class enclose
{
    struct nested // private member
    {
        void g() {}
    };
public:
    static nested f() { return nested{}; }
};
 
int main()
{
    //enclose::nested n1 = enclose::f(); // error: 'nested' is private
 
    enclose::f().g();       // OK: does not name 'nested'
    auto n2 = enclose::f(); // OK: does not name 'nested'
    n2.g();
}

[bearbeiten] 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 45 C++98 die Member einer verschachtelten Klasse können nicht
auf die umschließende Klasse und ihre Friends zugreifen
sie haben die gleichen Zugriffsrechte wie
andere Member der umschließenden Klasse
(löst auch CWG-Probleme #8 und #10)

[bearbeiten] Referenzen

  • C++23 Standard (ISO/IEC 14882:2024)
  • 11.4.12 Deklarationen verschachtelter Klassen [class.nest]
  • C++20 Standard (ISO/IEC 14882:2020)
  • 11.4.10 Deklarationen verschachtelter Klassen [class.nest]
  • C++17 Standard (ISO/IEC 14882:2017)
  • 12.2.5 Deklarationen verschachtelter Klassen [class.nest]
  • C++14 Standard (ISO/IEC 14882:2014)
  • 9.7 Deklarationen verschachtelter Klassen [class.nest]
  • C++11 Standard (ISO/IEC 14882:2011)
  • 9.7 Deklarationen verschachtelter Klassen [class.nest]
  • C++98 Standard (ISO/IEC 14882:1998)
  • 9.7 Deklarationen verschachtelter Klassen [class.nest]