클래스

클래스 (Classes)

사용자 정의 타입을 만들 때 가장 기본이 되는 게 클래스(class) 예요. 클래스는 사용자 정의 타입이에요. 클래스 타입은 선언 구문의 decl-specifier-seq에 나타나는 class-specifier로 정의돼요. class 지정자의 구문은 클래스 선언(class declaration) 문서를 참고하세요.

출처: cppreference

본문

클래스는 다음 종류의 멤버를 가질 수 있어요.

  1. 데이터 멤버: a. 비정적 데이터 멤버(비트 필드 포함) b. 정적 데이터 멤버
  2. 멤버 함수: a. 비정적 멤버 함수 b. 정적 멤버 함수
  3. 중첩 타입: a. 클래스 정의 안에서 정의된 중첩 클래스와 열거형 b. typedef나 타입 별칭(since C++11) 선언으로 정의된 기존 타입의 별칭 c. 자기 자신의 정의 안에서의 클래스 이름은 (생성자를 이름 붙일 때를 제외하고) 조회 목적상 자기 자신의 공개 멤버 타입 별칭으로 동작해요. 이를 주입된 클래스 이름(injected-class-name)이라고 해요.
  4. 클래스 안에서 정의된 모든 무범위 열거형의 열거자, 또는 using-선언으로 도입된 것들.

모든 멤버는 클래스 정의에서 한 번에 정의돼요. 이미 정의된 클래스에는 (네임스페이스의 멤버와 달리) 멤버를 추가할 수 없어요.

클래스 T의 멤버는 다음 경우 T를 자신의 이름으로 사용할 수 없어요.

  • 정적 데이터 멤버,
  • 멤버 함수,
  • 멤버 타입,
  • 멤버 템플릿,
  • (범위가 있는(scoped) 열거형이 아닌 한) 열거형의 열거자(since C++11), 또는
  • 멤버 익명 공용체의 멤버.

다만 비정적 데이터 멤버는 사용자 선언 생성자(user-declared constructors)가 없으면 이름 T를 사용할 수 있어요.

선언되거나 상속된 가상 멤버 함수가 하나 이상 있는 클래스는 다형적(polymorphic) 이에요. 이 타입의 객체는 다형적 객체이고, 객체 표현의 일부로 저장된 런타임 타입 정보를 가지는데, 이를 dynamic_casttypeid로 조회할 수 있어요. 가상 멤버 함수는 동적 바인딩(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)X0M(X0)의 요소들로 구성돼요.
    • X가 공용체 타입이면 M(X)는 모든 M(Ui)와 모든 Ui를 포함하는 집합의 합집합이에요. 여기서 각 UiXi번째 비정적 데이터 멤버의 타입이에요.
    • X가 요소 타입 Xe를 가진 배열 타입이면 M(X)XeM(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 암시적 수명 클래스가 사용자 제공 소멸자를 가질 수 있었음 금지