Geschachtelte Klassendeklarationen

Eine Klasse kann im Bereich einer anderen Klasse deklariert werden. Eine solche Klasse wird als "geschachtelte Klasse" bezeichnet. Geschachtelte Klassen gelten als innerhalb des Bereichs der eingeschlossenen Klasse und stehen für die Verwendung innerhalb dieses Bereichs zur Verfügung. Um auf eine geschachtelte Klasse aus einem anderen als dem unmittelbar einschließenden Bereich zu verweisen, müssen Sie einen vollqualifizierten Namen angeben.

Im folgenden Beispiel wird das Deklarieren geschachtelter Klassen veranschaulicht:

// nested_class_declarations.cpp
class BufferedIO
{
public:
   enum IOError { None, Access, General };

   // Declare nested class BufferedInput.
   class BufferedInput
   {
   public:
      int read();
      int good()
      {
         return _inputerror == None;
      }
   private:
       IOError _inputerror;
   };

   // Declare nested class BufferedOutput.
   class BufferedOutput
   {
      // Member list
   };
};

int main()
{
}

BufferedIO::BufferedInput und BufferedIO::BufferedOutput werden innerhalb BufferedIOdeklariert. Diese Klassennamen sind außerhalb des gültigen Bereichs der Klasse BufferedIO nicht sichtbar. Ein Objekt vom Typ BufferedIO enthält jedoch keine Objekte des Typs BufferedInput oder BufferedOutput.

Geschachtelte Klassen können Namen, Typnamen, Namen statischer Member und Enumeratoren nur aus der einschließenden Klasse direkt verwenden. Um Namen von anderen Klassenmembern zu verwenden, müssen Sie Zeiger, Verweise oder Objektnamen verwenden.

Im vorherigen Beispiel mit BufferedIO kann auf die Enumeration IOError direkt von Memberfunktionen in den geschachtelten Klassen BufferedIO::BufferedInput oder BufferedIO::BufferedOutput zugegriffen werden, wie in der good-Funktion gezeigt wird.

Hinweis

Geschachtelte Klassen deklarieren nur Typen innerhalb des gültigen Klassenbereichs. Sie führen nicht dazu, dass enthaltene Objekte der geschachtelten Klasse erstellt werden. Das vorhergehende Beispiel deklariert zwei geschachtelte Klassen, jedoch keine Objekte dieser Klassentypen.

Eine Ausnahme von der Bereichssichtbarkeit einer Deklaration der geschachtelten Klasse ist, wenn ein Typname zusammen mit einer Vorwärtsdeklaration deklariert ist. In diesem Fall ist der Klassenname, der von der Vorwärtsdeklaration deklariert wird, außerhalb der einschließenden Klasse sichtbar, wobei sein Bereich als kleinster einschließender Nichtklassenbereich definiert wird. Beispiel:

// nested_class_declarations_2.cpp
class C
{
public:
    typedef class U u_t; // class U visible outside class C scope
    typedef class V {} v_t; // class V not visible outside class C
};

int main()
{
    // okay, forward declaration used above so file scope is used
    U* pu;

    // error, type name only exists in class C scope
    u_t* pu2; // C2065

    // error, class defined above so class C scope
    V* pv; // C2065

    // okay, fully qualified name
    C::V* pv2;
}

Zugriffsrecht in geschachtelten Klassen

Das Schachteln einer Klasse in einer anderen Klasse gewährt keine speziellen Zugriffsrechte auf die Memberfunktionen der geschachtelten Klasse. Ebenso bieten Memberfunktionen der einschließenden Klasse keinen speziellen Zugriff auf die Member der geschachtelten Klasse.

Memberfunktionen in geschachtelten Klassen

Die Memberfunktionen, die in den geschachtelten Klassen deklariert werden, können im Dateibereich definiert werden. Das vorhergehende Beispiel könnte so aussehen:

// member_functions_in_nested_classes.cpp
class BufferedIO
{
public:
    enum IOError { None, Access, General };
    class BufferedInput
    {
    public:
        int read(); // Declare but do not define member
        int good(); //  functions read and good.
    private:
        IOError _inputerror;
    };

    class BufferedOutput
    {
        // Member list.
    };
};
// Define member functions read and good in
//  file scope.
int BufferedIO::BufferedInput::read()
{
   return(1);
}

int BufferedIO::BufferedInput::good()
{
    return _inputerror == None;
}
int main()
{
}

Im vorherigen Beispiel wird die Syntax für qualifizierten Typnamen verwendet, um den Funktionsnamen zu deklarieren. Die Deklaration:

BufferedIO::BufferedInput::read()

bedeutet "die read Funktion, die ein Mitglied der BufferedInput Klasse ist, die sich im Bereich der BufferedIO Klasse befindet." Da diese Deklaration die Syntax für qualifizierten Typnamen verwendet, sind Konstrukte des folgenden Formulars möglich:

typedef BufferedIO::BufferedInput BIO_INPUT;

int BIO_INPUT::read()

Die vorangehende Deklaration entspricht der vorherigen Deklaration, verwendet jedoch anstelle der Klassennamen einen typedef Namen.

Friend-Funktionen in geschachtelten Klassen

Die friend-Funktionen, die in einer geschachtelten Klasse deklariert werden, gelten als zum Bereich der geschachtelten Klasse zugehörig, nicht der einschließenden Klasse. Daher erhalten die friend-Funktionen keine besonderen Zugriffsrechte auf Member oder Memberfunktionen der einschließenden Klasse. Wenn Sie einen Namen verwenden möchten, der in einer geschachtelten Klasse in einer friend-Funktion deklariert ist, und diese friend-Funktion im Dateibereich definiert ist, verwenden Sie qualifizierte Typnamen wie folgt:

// friend_functions_and_nested_classes.cpp

#include <string.h>

enum
{
    sizeOfMessage = 255
};

char *rgszMessage[sizeOfMessage];

class BufferedIO
{
public:
    class BufferedInput
    {
    public:
        friend int GetExtendedErrorStatus();
        static char *message;
        static int  messageSize;
        int iMsgNo;
   };
};

char *BufferedIO::BufferedInput::message;
int BufferedIO::BufferedInput::messageSize;

int GetExtendedErrorStatus()
{
    int iMsgNo = 1; // assign arbitrary value as message number

    strcpy_s( BufferedIO::BufferedInput::message,
              BufferedIO::BufferedInput::messageSize,
              rgszMessage[iMsgNo] );

    return iMsgNo;
}

int main()
{
}

Der folgende Code zeigt die Funktion GetExtendedErrorStatus als friend-Funktion deklariert. In der Funktion, die im Dateibereich definiert ist, wird eine Nachricht von einem statischen Array in einen Klassenmember kopiert. Beachten Sie, dass eine bessere Implementierung von GetExtendedErrorStatus erfolgt, wenn dies wie folgt deklariert wird:

int GetExtendedErrorStatus( char *message )

Bei der vorherigen Schnittstelle können mehrere Klassen die Dienste dieser Funktion verwenden, indem eine Speicheradresse übergeben wird, an welche die Fehlermeldung kopiert werden soll.

Siehe auch

Klassen und Strukturen