Namespaces
Variants

Nested classes

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Eine Deklaration einer class/struct oder union kann innerhalb einer anderen Klasse erscheinen. Eine solche Deklaration deklariert eine nested class .

Erklärung

Der Name der geschachtelten Klasse existiert im Gültigkeitsbereich der umschließenden Klasse, und Namenssuche von einer Memberfunktion der geschachtelten Klasse besucht den Gültigkeitsbereich der umschließenden Klasse nach Prüfung des Gültigkeitsbereichs der geschachtelten Klasse. Wie jedes Mitglied seiner umschließenden Klasse hat die geschachtelte Klasse Zugriff auf alle Namen (private, protected, etc.), auf die die umschließende Klasse Zugriff hat, ist aber ansonsten unabhängig und hat keinen speziellen Zugriff auf den this pointer der umschließenden Klasse. Deklarationen in einer geschachtelten Klasse können alle Mitglieder der umschließenden Klasse verwenden, entsprechend den üblichen Verwendungsregeln für nicht-statische Mitglieder.

int x, y; // Globale Variablen
class enclose // Umschließende Klasse
{
    // Hinweis: Private Member
    int x;
    static int s;
public:
    struct inner // Verschachtelte Klasse
    {
        void f(int i)
        {
            x = i; // Fehler: Kann nicht auf nicht-statisches enclose::x ohne Instanz schreiben
            int a = sizeof x; // Fehler bis C++11,
                              // OK in C++11: Operand von sizeof wird nicht ausgewertet,
                              // diese Verwendung des nicht-statischen enclose::x ist erlaubt.
            s = i;   // OK: Kann dem statischen enclose::s zuweisen
            ::x = i; // OK: Kann globalem x zuweisen
            y = i;   // OK: Kann globalem y zuweisen
        }
        void g(enclose* p, int i)
        {
            p->x = i; // OK: Weist enclose::x zu
        }
    };
};

Friend Funktionen, die innerhalb einer geschachtelten Klasse definiert sind, haben keinen speziellen Zugriff auf die Member der umschließenden Klasse, selbst wenn die Suche aus dem Körper einer Memberfunktion, die innerhalb einer geschachtelten Klasse definiert ist, die privaten Member der umschließenden Klasse finden kann.

Out-of-class-Definitionen der Member einer geschachtelten Klasse erscheinen im Namensraum 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ärtsdeklariert und später definiert werden, entweder innerhalb desselben einschließenden Klassenkörpers oder außerhalb davon:

class enclose
{
    class nested1;    // Vorwärtsdeklaration
    class nested2;    // Vorwärtsdeklaration
    class nested1 {}; // Definition der geschachtelten Klasse
};
class enclose::nested2 {}; // Definition der geschachtelten Klasse

Verschachtelte Klassendeklarationen folgen Zugriffsspezifizierern für Mitglieder , eine private Mitgliedsklasse kann nicht außerhalb des Gültigkeitsbereichs der einschließenden Klasse benannt werden, obwohl Objekte dieser Klasse manipuliert werden können:

class enclose
{
    struct nested // privates Mitglied
    {
        void g() {}
    };
public:
    static nested f() { return nested{}; }
};
int main()
{
    //enclose::nested n1 = enclose::f(); // Fehler: 'nested' ist privat
    enclose::f().g();       // OK: benennt 'nested' nicht
    auto n2 = enclose::f(); // OK: benennt 'nested' nicht
    n2.g();
}

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 45 C++98 die Mitglieder einer geschachtelten Klasse können
nicht auf die umschließende Klasse und ihre Freunde zugreifen
sie haben dieselben Zugriffsrechte wie
andere Mitglieder der umschließenden Klasse
(löst ebenfalls CWG Probleme #8 und #10)

Referenzen

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