클래스
클래스 (Classes)
사용자 정의 타입을 만들 때 가장 기본이 되는 게 클래스(class) 예요. 클래스는 사용자 정의 타입이에요. 클래스 타입은 선언 구문의 decl-specifier-seq에 나타나는 class-specifier로 정의돼요. class 지정자의 구문은 클래스 선언(class declaration) 문서를 참고하세요.
출처: cppreference
본문
클래스는 다음 종류의 멤버를 가질 수 있어요.
- 데이터 멤버: a. 비정적 데이터 멤버(비트 필드 포함) b. 정적 데이터 멤버
- 멤버 함수: a. 비정적 멤버 함수 b. 정적 멤버 함수
- 중첩 타입:
a. 클래스 정의 안에서 정의된 중첩 클래스와 열거형
b.
typedef나 타입 별칭(since C++11) 선언으로 정의된 기존 타입의 별칭 c. 자기 자신의 정의 안에서의 클래스 이름은 (생성자를 이름 붙일 때를 제외하고) 조회 목적상 자기 자신의 공개 멤버 타입 별칭으로 동작해요. 이를 주입된 클래스 이름(injected-class-name)이라고 해요. - 클래스 안에서 정의된 모든 무범위 열거형의 열거자, 또는
using-선언으로 도입된 것들.
모든 멤버는 클래스 정의에서 한 번에 정의돼요. 이미 정의된 클래스에는 (네임스페이스의 멤버와 달리) 멤버를 추가할 수 없어요.
클래스 T의 멤버는 다음 경우 T를 자신의 이름으로 사용할 수 없어요.
- 정적 데이터 멤버,
- 멤버 함수,
- 멤버 타입,
- 멤버 템플릿,
- (범위가 있는(scoped) 열거형이 아닌 한) 열거형의 열거자(since C++11), 또는
- 멤버 익명 공용체의 멤버.
다만 비정적 데이터 멤버는 사용자 선언 생성자(user-declared constructors)가 없으면 이름 T를 사용할 수 있어요.
선언되거나 상속된 가상 멤버 함수가 하나 이상 있는 클래스는 다형적(polymorphic) 이에요. 이 타입의 객체는 다형적 객체이고, 객체 표현의 일부로 저장된 런타임 타입 정보를 가지는데, 이를 dynamic_cast와 typeid로 조회할 수 있어요. 가상 멤버 함수는 동적 바인딩(dynamic binding)에 참여해요.
선언되거나 상속된 순수 가상 멤버 함수가 하나 이상 있는 클래스는 추상 클래스(abstract class) 이에요. 이 타입의 객체는 생성할 수 없어요.
constexpr 생성자를 가진 클래스는 리터럴 타입(LiteralType) 이에요. 이 타입의 객체는 컴파일 타임에 constexpr 함수로 조작할 수 있어요. (since C++11)
클래스의 특성 (Properties of classes)
사소하게 복사 가능한 클래스 (Trivially copyable class)
사소하게 복사 가능한(trivially copyable) 클래스는 다음을 만족하는 클래스예요.
- 적격한(eligible) 복사 생성자, 이동 생성자, 복사 대입 연산자, 이동 대입 연산자가 하나 이상 있고,
- 각 적격한 복사 생성자가 사소하고(trivial),
- 각 적격한 이동 생성자가 사소하고,
- 각 적격한 복사 대입 연산자가 사소하고,
- 각 적격한 이동 대입 연산자가 사소하고,
- 삭제되지 않은 사소한 소멸자를 가져요.
사소한 클래스 (Trivial class)
사소한(trivial) 클래스는 다음을 만족하는 클래스예요.
- 사소하게 복사 가능하고,
- 각각이 사소한 적격한 기본 생성자가 하나 이상 있어요. (C++26에서 deprecated)
표준 레이아웃 클래스 (Standard-layout class)
표준 레이아웃(standard-layout) 클래스는 다음을 만족하는 클래스예요.
- 비-표준-레이아웃 클래스 타입(또는 그런 타입의 배열)이나 참조 타입의 비정적 데이터 멤버가 없고,
- 가상 함수도 가상 베이스 클래스도 없고,
- 모든 비정적 데이터 멤버가 같은 접근 제어를 가지며,
- 비-표준-레이아웃 베이스 클래스가 없고,
- 계층에서 비정적 데이터 멤버를 가지는 클래스가 오직 하나이고,
- 비공식적으로, 어떤 베이스 클래스도 첫 번째 비정적 데이터 멤버와 같은 타입을 가지지 않아요. 공식적으로는, 클래스를
S라 할 때 타입의 집합M(S)의 어떤 요소도 베이스 클래스로 가지지 않아요. 여기서 타입X에 대한M(X)는 다음과 같이 정의돼요.X가 (상속받은) 비정적 데이터 멤버가 없는 비-공용체 클래스 타입이면M(X)는 빈 집합이에요.X가 첫 번째 비정적 데이터 멤버의 타입이X0인(그 멤버가 익명 공용체일 수 있는) 비-공용체 클래스 타입이면M(X)는X0과M(X0)의 요소들로 구성돼요.X가 공용체 타입이면M(X)는 모든M(Ui)와 모든Ui를 포함하는 집합의 합집합이에요. 여기서 각Ui는X의i번째 비정적 데이터 멤버의 타입이에요.X가 요소 타입Xe를 가진 배열 타입이면M(X)는Xe와M(Xe)의 요소들로 구성돼요.X가 비-클래스, 비-배열 타입이면M(X)는 빈 집합이에요.
표준 레이아웃 구조체(standard-layout struct)는 struct 또는 class 키워드로 정의된 표준 레이아웃 클래스예요. 표준 레이아웃 공용체(standard-layout union)는 union 키워드로 정의된 표준 레이아웃 클래스예요. (since C++11)
암시적 수명 클래스 (Implicit-lifetime class)
암시적 수명(implicit-lifetime) 클래스는 다음을 만족하는 클래스예요.
- 소멸자가 사용자 선언(until C++11)이거나 사용자 제공(user-provided)(since C++11)이 아닌 집계(aggregate)이거나,
- 사소한 적격한 생성자가 하나 이상 있고 사소하고 삭제되지 않은 소멸자가 있어요.
참고: 암시적 수명 특성은 결함 보고 P0593R6에 의해 명확해졌어요.
POD 클래스 (POD class)
POD(Plain Old Data) 클래스는 다음을 만족하는 클래스예요.
- 집계이고,
- 사용자 선언 복사 대입 연산자가 없고,
- 사용자 선언 소멸자가 없고,
- 비-POD 클래스 타입(또는 그런 타입의 배열)이나 참조 타입의 비정적 데이터 멤버가 없어요. (until C++11)
- 사소한 클래스이고,
- 표준 레이아웃 클래스이고,
- 비-POD 클래스 타입(또는 그런 타입의 배열)의 비정적 데이터 멤버가 없어요. (since C++11)
POD 구조체는 비-공용체 POD 클래스예요. POD 공용체는 POD 클래스인 공용체예요. (C++20에서 deprecated)
결함 보고 (Defect reports)
다음 동작 변경 결함 보고는 이전에 발표된 C++ 표준에 소급 적용됐어요.
| DR | 적용 대상 | 발표된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 148 | C++98 | POD 클래스가 그들 자신 POD(스칼라) 타입인 멤버 포인터를 포함할 수 없었음 | 제한 제거 |
| CWG 383 | C++98 | POD 클래스에서 복사 대입 연산자나 소멸자가 정의되지 않으면 사용자 선언될 수 있었음 | 허용되지 않음 |
| CWG 1363 | C++11 | 사소한 기본 생성자와 비-사소한 기본 생성자를 동시에 가진 클래스가 사소할 수 있었음 | 비-사소함 |
| CWG 1496 | C++11 | 모든 생성자가 삭제(정의)된 것으로만 선언된 클래스가 사소할 수 있었음 | 비-사소함 |
| CWG 1672 | C++11 | 여러 개의 빈 베이스 클래스를 가진 클래스가 표준 레이아웃 클래스일 수 있었음 | 표준 레이아웃 클래스가 아님 |
| CWG 1734 | C++11 | 사소하게 복사 가능한 클래스가 비-사소한 삭제된 복사/이동 생성자/대입 연산자를 가질 수 없었음 | 삭제되면 사소할 수 있음 |
| CWG 1813 | C++11 | 비정적 데이터 멤버를 상속하는 베이스 클래스를 가진 클래스는 결코 표준 레이아웃 클래스가 아니었음 | 표준 레이아웃 클래스일 수 있음 |
| CWG 1881 | C++11 | 표준 레이아웃 클래스와 그 베이스 클래스에 대해, 이름 없는 비트 필드가 데이터 멤버를 선언하는 다른 클래스에 선언될 수 있었음 | 모든 비정적 데이터 멤버와 비트 필드가 같은 클래스에서 먼저 선언돼야 함 |
| CWG 1909 | C++98 | 멤버 템플릿이 그 클래스와 같은 이름을 가질 수 있었음 | 금지 |
| CWG 2120 | C++11 | 표준 레이아웃 클래스를 판단하는 M(X) 정의에서 첫 멤버가 배열인 클래스의 경우를 고려하지 않았음 |
M(X) 정의에서 이 경우를 다룸 |
| CWG 2605 | C++98 | 암시적 수명 클래스가 사용자 제공 소멸자를 가질 수 있었음 | 금지 |