Udostępnij za pośrednictwem


Zagnieżdżone deklaracje klas

Klasa może być zadeklarowana w zakresie innej klasy. Taka klasa jest nazywana "klasą zagnieżdżona". Klasy zagnieżdżone są uważane za należące do zakresu otaczającej klasy i są dostępne do użycia w tym zakresie. Aby odwołać się do klasy zagnieżdżonej z zakresu innego niż jego bezpośredni zasięg, należy użyć w pełni kwalifikowanej nazwy.

Poniższy przykład pokazuje sposób deklarowania klas zagnieżdżonych:

// 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 i BufferedIO::BufferedOutput są deklarowane w obrębie BufferedIO. Nazwy klas nie są widoczne w zakresie klasy BufferedIO. Jednak obiekt typu BufferedIO nie zawiera żadnych obiektów typu BufferedInput lub BufferedOutput.

Klasy zagnieżdżone mogą bezpośrednio korzystać z nazw, nazwy typów, nazw statycznych składowych i wyliczeń tylko z otaczającej klasy. Aby używać nazw innych składowych klasy, należy użyć wskaźników, odwołań lub nazw obiektów.

W poprzednim przykładzie BufferedIO, wyliczenie IOError jest dostępne bezpośrednio przez funkcje składowe w klasach zagnieżdżonych BufferedIO::BufferedInput lub BufferedIO::BufferedOutput, jak pokazano w funkcji good.

Uwaga

Klasy zagnieżdżone deklarują tylko typy w zakresie klasy. Nie przyczyniają się do tworzenia obiektów, w których zagnieżdżone są klasy. Poprzedni przykład deklaruje dwie klasy zagnieżdżone, ale nie deklaruje żadnych obiektów tego typu klas.

Wyjątkiem zakresu widoczności deklaracji klasy zagnieżdżonej jest nazwa typu zadeklarowana wraz z deklaracją do przodu. W tym przypadku nazwa klasy zadeklarowanej deklaracji do przodu jest widoczna spoza otaczającej klasy z jej zakresem zdefiniowanym jako najmniejszy otaczający zakres. Przykład:

// 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;
}

Uprawnienia dostępu w klasach zagnieżdżonych

Zagnieżdżanie klasy w innej klasie nie daje specjalnych uprawnień dostępu do funkcji składowych klasy zagnieżdżonej. Podobnie funkcje składowe otaczającej klasy nie mają specjalnego dostępu do składowych klasy zagnieżdżonej.

Funkcje składowe w klasach zagnieżdżonych

Funkcje składowe zadeklarowane w klasach zagnieżdżonych można zdefiniować w zakresie pliku. Powyższy przykład mógł zostać napisany:

// 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()
{
}

W poprzednim przykładzie składnia kwalifikowanego typu-name służy do deklarowania nazwy funkcji. Deklaracja:

BufferedIO::BufferedInput::read()

oznacza " read funkcję, która jest składową BufferedInput klasy, która znajduje się w zakresie BufferedIO klasy". Ponieważ ta deklaracja używa składni kwalifikowanej nazwy typu, możliwe są konstrukcje następującego formularza:

typedef BufferedIO::BufferedInput BIO_INPUT;

int BIO_INPUT::read()

Poprzednia deklaracja jest równoważna poprzedniej deklaracji, ale używa typedef nazwy zamiast nazw klas.

Przyjazne funkcje w klasach zagnieżdżonych

Funkcje zaprzyjaźnione zadeklarowane w zagnieżdżonej klasie są uważane za w zakresie zagnieżdżonej klasy, a nie w otaczającej klasie. W związku z tym funkcje znajome nie uzyskują specjalnych uprawnień dostępu do elementów członkowskich lub funkcji składowych otaczającej klasy. Jeśli chcesz użyć nazwy zadeklarowanej w zagnieżdżonej klasie w funkcji zaprzyjaźnionej, a funkcja znajoma jest zdefiniowana w zakresie pliku, użyj kwalifikowanych nazw typów w następujący sposób:

// 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()
{
}

Poniższy kod przedstawia funkcję GetExtendedErrorStatus zadeklarowaną jako funkcja znajoma. W funkcji zdefiniowanej w zakresie pliku komunikat jest kopiowany z tablicy statycznej do składowej klasy. Należy pamiętać, że lepszą implementacją GetExtendedErrorStatus programu jest zadeklarowanie jej jako:

int GetExtendedErrorStatus( char *message )

W poprzednim interfejsie kilka klas może używać usług tej funkcji, przekazując lokalizację pamięci, w której ma zostać skopiowany komunikat o błędzie.

Zobacz też

Klasy i struktury