중첩 클래스
중첩 클래스 (Nested classes)
클래스 안에 또 클래스를 선언할 수 있다는 걸 알고 계셨나요? 이렇게 다른 클래스 안에 선언된 클래스를 중첩 클래스(nested class)라고 불러요.
출처: cppreference
본문
클래스/구조체(struct) 또는 공용체(union)의 선언이 다른 클래스 안에 나타날 수 있어요. 이런 선언은 중첩 클래스를 선언해요.
설명
중첩 클래스의 이름은 바깥 클래스(enclosing class)의 스코프에 존재해요. 그리고 중첩 클래스의 멤버 함수에서 이름 탐색(name lookup)을 하면, 중첩 클래스 자신의 스코프를 먼저 조사한 뒤 바깥 클래스의 스코프를 방문해요.
바깥 클래스의 다른 멤버와 마찬가지로, 중첩 클래스는 바깥 클래스가 접근할 수 있는 모든 이름(private, protected 등 포함)에 접근할 수 있어요. 하지만 그 외에는 독립적이며, 바깥 클래스의 this 포인터에 대한 특별한 접근 권한은 없어요. 중첩 클래스 안의 선언은 바깥 클래스의 멤버들을 사용할 수 있는데, 이때 비정적(non-static) 멤버에 대한 일반적인 사용 규칙을 따르게 돼요.
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) {} // 정의
중첩 클래스는 전방 선언(forward declaration)을 한 뒤 나중에 정의할 수도 있어요. 이때 정의는 같은 바깥 클래스 본문 안이나 바깥에서 할 수 있어요:
class enclose
{
class nested1; // 전방 선언
class nested2; // 전방 선언
class nested1 {}; // 중첩 클래스의 정의
};
class enclose::nested2 {}; // 중첩 클래스의 정의
중첩 클래스 선언은 멤버 접근 지정자(member access specifier)를 따르는데, 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();
}
결함 보고 (Defect reports)
| DR | 적용 대상 | 발표 당시 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 45 | C++98 | 중첩 클래스의 멤버는 바깥 클래스와 그 friend에 접근할 수 없음 | 바깥 클래스의 다른 멤버와 동일한 접근 권한을 가짐 (CWG 이슈 #8과 #10도 해결) |