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

class/struct 또는 union 의 선언이 다른 클래스 내부에 나타날 수 있습니다. 이러한 선언은 중첩 클래스(nested class) 를 선언합니다.

설명

중첩 클래스의 이름은 외부 클래스의 범위 내에 존재하며, 중첩 클래스의 멤버 함수에서 이름 검색(name lookup)은 중첩 클래스의 범위를 검사한 후 외부 클래스의 범위를 방문합니다. 외부 클래스의 다른 멤버와 마찬가지로, 중첩 클래스는 외부 클래스가 접근할 수 있는 모든 이름(private, protected 등)에 접근할 수 있지만, 그 외에는 독립적이며 외부 클래스의 this pointer 에 대한 특별한 접근 권한을 갖지 않습니다. 중첩 클래스의 선언은 비정적 멤버에 대한 일반적인 사용 규칙 을 따라 외부 클래스의 모든 멤버를 사용할 수 있습니다.

int x, y; // 전역 변수
class enclose // 외부 클래스
{
    // 참고: private 멤버
    int x;
    static int s;
public:
    struct inner // 중첩 클래스
    {
        void f(int i)
        {
            x = i; // 오류: 인스턴스 없이 비정적 enclose::x에 쓸 수 없음
            int a = sizeof x; // C++11까지 오류,
                              // C++11에서 OK: sizeof의 피연산자는 평가되지 않으며,
                              // 비정적 enclose::x의 이 사용은 허용됨
            s = i;   // OK: 정적 enclose::s에 할당 가능
            ::x = i; // OK: 전역 x에 할당 가능
            y = i;   // OK: 전역 y에 할당 가능
        }
        void g(enclose* p, int i)
        {
            p->x = i; // OK: enclose::x에 할당
        }
    };
};

Friend 함수가 중첩 클래스 내부에서 정의된 경우, 중첩 클래스 내부에서 정의된 멤버 함수의 본문에서 조회 시 바깥쪽 클래스의 private 멤버를 찾을 수 있더라도, 바깥쪽 클래스의 멤버에 대한 특별한 접근 권한을 갖지 않습니다.

중첩 클래스의 멤버에 대한 클래스 외부 정의는 외부 클래스의 네임스페이스에 나타납니다:

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

중첩 클래스는 전방 선언될 수 있으며, 동일한 외부 클래스 본문 내에서나 외부에서 나중에 정의될 수 있습니다:

class enclose
{
    class nested1;    // 전방 선언
    class nested2;    // 전방 선언
    class nested1 {}; // 중첩 클래스 정의
};
class enclose::nested2 {}; // 중첩 클래스 정의

중첩 클래스 선언은 멤버 접근 지정자를 따르며, private 멤버 클래스는 외부 클래스의 범위 밖에서는 이름을 사용할 수 없지만, 해당 클래스의 객체는 조작될 수 있습니다:

class enclose
{
    struct nested // private 멤버
    {
        void g() {}
    };
public:
    static nested f() { return nested{}; }
};
int main()
{
    //enclose::nested n1 = enclose::f(); // 오류: 'nested'는 private입니다
    enclose::f().g();       // OK: 'nested'를 명시적으로 언급하지 않음
    auto n2 = enclose::f(); // OK: 'nested'를 명시적으로 언급하지 않음
    n2.g();
}

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
CWG 45 C++98 중첩 클래스의 멤버들이
외부 클래스와 그 friend들에 접근할 수 없음
외부 클래스의 다른 멤버들과
동일한 접근 권한을 가짐
(CWG 이슈 #8과 #10도 함께 해결됨)

참고문헌

  • C++23 표준 (ISO/IEC 14882:2024):
  • 11.4.12 중첩 클래스 선언 [class.nest]
  • C++20 표준(ISO/IEC 14882:2020):
  • 11.4.10 중첩 클래스 선언 [class.nest]
  • C++17 표준 (ISO/IEC 14882:2017):
  • 12.2.5 중첩 클래스 선언 [class.nest]
  • C++14 표준(ISO/IEC 14882:2014):
  • 9.7 중첩 클래스 선언 [class.nest]
  • C++11 표준 (ISO/IEC 14882:2011):
  • 9.7 중첩 클래스 선언 [class.nest]
  • C++98 표준 (ISO/IEC 14882:1998):
  • 9.7 중첩 클래스 선언 [class.nest]