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ż
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla