- C++11에 도입
// unscoped enum:
// enum [identifier] [: type] {enum-list};
// scoped enum:
// enum [class|struct] [identifier] [: type] {enum-list};
// Forward declaration of enumerations (C++11):
enum A : int; // non-scoped enum must have type specified
enum class B; // scoped enum defaults to int but ...
enum class C : short; // ... may have any integral underlying type
매계 변수#
identifier:
열거자의 기본 형식이며, 모든 열거자는 동일한 기본 형식을 갖습니다. 모든 정수 계열 형식이 가능합니다.type
: 열거자의 기본 형식이며, 모든 열거자는 동일한 기본 형식을 갖습니다. 모든 정수 계열 형식이 가능합니다.enum-list
: 열거형에서 열거자의 쉼표로 구분된 목록입니다. 범위에 있는 모든 열거자 또는 변수 이름은 고유해야 합니다. 하지만 값이 중복될 수 있습니다. 범위가 지정되지 않은 열거형에서 범위는 주변 범위입니다. 범위가 지정된 열거형에서 범위는 그 자체입니다enum-list
. 범위가 지정된 열거형에서 목록은 비어 있을 수 있으며 실제로 새 정수 계열 형식을 정의합니다.class
: 선언에서 이 키워드(keyword) 사용하여 열거형의 범위가 지정되고identifier
반드시 제공해야 합니다. 이 컨텍스트에서 의미상 동일한 키워드(keyword) 대신class
사용할struct
수도 있습니다.
열거자 스코프#
- 명명된 상수 표현되는 값의 범위를 설명하는 컨텍스트 제공
namespace CardGame_Scoped
{
enum class Suit { Diamonds, Hearts, Clubs, Spades };
void PlayCard(Suit suit)
{
if (suit == Suit::Clubs) // Enumerator must be qualified by enum type
{ /*...*/}
}
}
namespace CardGame_NonScoped
{
enum Suit { Diamonds, Hearts, Clubs, Spades };
void PlayCard(Suit suit)
{
if (suit == Clubs) // Enumerator is visible without qualification
{ /*...*/
}
}
}
값 할당 규칙#
- case1
- 따로 할당 값을 지정하지 않으면 좌측을 기준으로 0번부터 1씩 증가한 값 부여
// 0, 1, 2, 3
enum Suit { Diamonds , Hearts, Clubs, Spades };
- case2
- 맨 앞의 요소에 대해 할당값이 주어지면 그 값부터 1씩 증가
// 1, 2, 3, 4
enum Suit { Diamonds = 1 , Hearts, Clubs, Spades };
- case3
- 여러 요소에 할당값이 주어진 경우는 값이 주어진 요소의 기준부터 순차적으로 증가된 값이 할당되며 만약 증가하다 값이 미리 할당되어져 있는 요소를 다시 만날 시 해당 값부터 다시 증가한다.
// 1, 2, 1, 2
enum Suit { Diamonds = 1 , Hearts, Clubs = 1, Spades };
- case4
- 임의의 값을 하나하나 다 할당해둔 경우 해당 값을 가진다.
// 4, 3, 2, 1
enum Suit { Diamonds = 4 , Hearts = 3, Clubs = 2, Spades = 1 };
캐스팅 규칙#
- enum Suit { Diamonds, Hearts, Clubs, Spades }; ⇒ non scoped enun
- 약타입 이므로 암시적 형변환이 가능하다.
//int 자료형으로 자동 변환되어 0이 출력된다.
cout << Diamonds;
- enum class Suit { Diamonds, Hearts, Clubs, Spades }; ⇒ scoped enum
- 강타입 이므로 암시적 형변환이 되지 않고 명시적 형변환 필요
using enum Suit;
//암시적 형변환이 안되기 때문에 Suit 형은 cout 에서 출력이 불가능 하므로 컴파일 에러 발생
cout << Suit::Diamonds;
//명시적 형변환을 통해 int 자료형을로 캐스팅 하면 출력 가능
cout << (int)Suit::Diamonds;
강 타입과 약 타입, 정적 타입과 동적 타입#
강타입#
- 강타입은 다른 형끼리 변환이 금지되어 있으며 만약 형변환을 하고 싶다면 명시적으로 타입을 변환시켜줘야 한다.
약타입#
- 다른 형끼리 변환이 가능하며 암시적 변환 또한 허용하기도 한다.
정적 타입#
- 컴파일 시에 타입이 결정되므로 자료형을 명시적으로 지정해 줘야 한다.
동적 타입#
- 런타임에서 타입이 결정되므로 자료형을 명시적으로 지정해지 않아도 작동한다.
열거자가 없는 열거형#
- /std:c++17
- 의도하지 않은 암시적 변환으로 인한 미묘한 오류가 발생할 가능성을 제거할 수 있습니다.
예시 코드#
enum class byte : unsigned char { };
enum class E : int {};
//위에서 E : int { e1 = 0 }; 으로 초기화 한것과 같은 결과
E e1{ 0 };
E e2 = E{ 0 };
struct X
{
E e{ 0 };
X() : e{ 0 } { }
};
E* p = new E{ 0 };
void f(E e) {};
int main()
{
f(E{ 0 });
byte i{ 42 };
byte j = byte{ 42 };
cout << (int)e1 << endl;
// unsigned char c = j; // C2440: 'initializing': cannot convert from 'byte' to 'unsigned char'
return 0;
}
링크#
https://learn.microsoft.com/ko-kr/cpp/cpp/enumerations-cpp?view=msvc-170