Enum 대 강력한 형식의 열거 형


84

저는 C ++ 프로그래밍의 초보자입니다.

오늘 저는 새로운 주제 인 strong typed를 발견했습니다 enum. 나는 그것을 조금 조사했지만 지금까지 왜 이것이 필요한지 그리고 같은 용도가 무엇인지 알 수 없습니다.

예를 들어 다음과 같은 경우 :

enum xyz{a, b, c};
/*a = 0, b = 1, c = 2, (Typical C format)*/

왜 우리는 다음과 같이 작성해야합니까?

enum class xyz{a, b, c};

여기서 무엇을하려고합니까? 나의 가장 중요한 의심은 그것을 사용하는 방법입니다. 제가 이해할 수 있도록 작은 예를 들어 주시겠습니까?

답변:


114

예, 첫 번째 예 : 이전 스타일 열거 형에는 자체 범위가 없습니다.

enum Animals {Bear, Cat, Chicken};
enum Birds {Eagle, Duck, Chicken}; // error! Chicken has already been declared!

enum class Fruits { Apple, Pear, Orange };
enum class Colours { Blue, White, Orange }; // no problem!

둘째, 암시 적으로 정수 유형으로 변환되어 이상한 동작이 발생할 수 있습니다.

bool b = Bear && Duck; // what?

마지막으로 C ++ 11 열거 형의 기본 정수 유형을 지정할 수 있습니다.

enum class Foo : char { A, B, C};

이전에는 기본 유형이 지정되지 않아 플랫폼 간 호환성 문제가 발생할 수 있습니다. 편집 주석에서 C ++ 11에서 "이전 스타일"열거 형의 기본 정수 유형을 지정할 수도 있다는 것이 지적되었습니다.


우리가 선언해야합니까 / 정의 enum class Coloursenum class Fruits. 내가 VS 2010의 코드를 쓸 때이 오류가 발생하기 때문에 "expects a defination or a tag name"아래를 class.
Rasmi Ranjan Nayak

또한 : C ++ 98에서와 같이 C ++ 11의 "ordinary"열거 형의 경우 기본 기본 유형이 정의되지 않았습니다
bruziuz

2
또한 : 기본 유형이 지정된 경우 enum-s의 정방향 선언을 수행 할 수 있습니다. C ++ 11, C ++ 98의 일반 열거 형의 경우 허용되지 않습니다. Microsoft 컴파일러는 enum의 포워드 선언을 허용하지만 MS 확장 일 뿐이며 표준이 아닙니다 (예 : gcc에서는 허용하지 않음). 따라서 이제 그런 것은 합법적입니다. enum ForwardDeclare : std :: uint8_t;
bruziuz

암시 적으로 정수 형식으로 변환하는 범위가 지정된 열거 형을 가질 수 있습니까?
SS Anne

17

이 IBM 페이지 에는 열거 형에 대한 좋은 기사 가 있습니다. 매우 자세하고 잘 작성되어 있습니다. 다음은 간단히 말해서 몇 가지 중요한 사항입니다.

범위가 지정된 열거 형은 완전한 형식 안전성, 잘 정의 된 기본 형식, 범위 문제 및 전달 선언과 같은 일반 열거 형에서 발생하는 대부분의 제한 사항을 해결합니다.

  • 범위가 지정된 열거 형의 모든 암시 적 변환을 다른 형식으로 허용하지 않음으로써 형식 안전성을 얻을 수 있습니다.
  • 새 범위가 생기고 열거 형이 더 이상 둘러싸는 범위에 포함되지 않아 이름 충돌이 발생하지 않습니다.
  • 범위가 지정된 열거 형은 열거 형의 기본 유형을 지정할 수있는 기능을 제공하며 범위가 지정된 열거 형의 경우 지정하지 않도록 선택하면 기본값은 int입니다.
  • 고정 된 기본 형식을 가진 모든 열거 형은 앞으로 선언 될 수 있습니다.

2
세 번째와 네 번째 점은 범위가 지정된 열거에만 국한되지 않습니다. 모든 열거의 기본 유형을 지정할 수 있습니다.
Mike Seymour

1
누구든지 덜 깨진 PDF 버전에 대한 링크가 있습니까? 그것의 코드 예제는 내 PDF 뷰어에서 렌더링되지 않으므로 상상력에 많은 것을 남깁니다.
Sara Sinback 19

11

의 값은 C- 열거 형이 아닌 enum class실제로 유형 입니다.enum classunderlying_type

enum xyz { a, b, c};
enum class xyz_c { d, f, e };

void f(xyz x)
{
}

void f_c(xyz_c x)
{
}

// OK.
f(0);
// OK for C++03 and C++11.
f(a);
// OK with C++11.
f(xyz::a);
// ERROR.
f_c(0);
// OK.
f_c(xyz_c::d);

5

열거 형 클래스 ( "new enums", "strong enums")는 기존 C ++ 열거 형의 세 가지 문제를 해결합니다.

  1. 관습 enums적으로 암시 적으로로 변환하여 int누군가 열거 형이 정수로 작동하는 것을 원하지 않을 때 오류를 발생시킵니다.
  2. 기존 enums의 열거자를 주변 범위로 내 보내면 이름 충돌이 발생합니다.
  3. 의 기본 유형을 enum지정할 수 없으므로 혼동, 호환성 문제가 발생하고 앞으로 선언 할 수 없습니다.

enum class ( "strong enums")은 강력한 형식과 범위가 지정됩니다.

enum Alert { green, yellow, orange, red }; // traditional enum

enum class Color { red, blue };   // scoped and strongly typed enum
                                  // no export of enumerator names into enclosing scope
                                  // no implicit conversion to int
enum class TrafficLight { red, yellow, green };

Alert a = 7;              // error (as ever in C++)
Color c = 7;              // error: no int->Color conversion

int a2 = red;             // ok: Alert->int conversion
int a3 = Alert::red;      // error in C++98; ok in C++11
int a4 = blue;            // error: blue not in scope
int a5 = Color::blue;     // error: not Color->int conversion

Color a6 = Color::blue;   // ok

표시된대로 기존 열거 형은 평소와 같이 작동하지만 이제 선택적으로 열거 형 이름으로 한정 할 수 있습니다.

새 열거 형은 기존 열거 형 (이름 값)의 측면과 클래스 측면 (범위가 지정된 멤버 및 변환 없음)을 결합하기 때문에 "열거 형 클래스"입니다.

기본 유형을 지정할 수 있으므로 상호 운용성이 더 간단하고 열거 크기가 보장됩니다.

enum class Color : char { red, blue };  // compact representation

enum class TrafficLight { red, yellow, green };  // by default, the underlying type is int

enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U };   // how big is an E?
                                                 // (whatever the old rules say;
                                                 // i.e. "implementation defined")

enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U };   // now we can be specific

또한 열거 형을 앞으로 선언 할 수 있습니다.

enum class Color_code : char;     // (forward) declaration
void foobar(Color_code* p);       // use of forward declaration
// ...
enum class Color_code : char { red, yellow, green, blue }; // definition

기본 유형은 부호있는 또는 부호없는 정수 유형 중 하나 여야합니다. 기본값은 int입니다.

표준 라이브러리에서 enum클래스는 다음에 사용됩니다.

  1. 매핑 시스템 특정 오류 코드 : In <system_error>: enum class errc;
  2. 포인터 안전 표시기 : In <memory>:enum class pointer_safety { relaxed, preferred, strict };
  3. I / O 스트림 오류 : 입력 <iosfwd>:enum class io_errc { stream = 1 };
  4. 비동기 통신 오류 처리 : In <future>:enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };

이들 중 일부에는 ==정의 된 것과 같은 연산자가 있습니다 .


3

열거 형 범위

열거 형은 열거자를 주변 범위로 내 보냅니다. 여기에는 두 가지 단점이 있습니다. 첫째, 동일한 범위에서 선언 된 서로 다른 열거 형의 두 열거자가 동일한 이름을 갖는 경우 이름 충돌이 발생할 수 있습니다. 둘째, 열거 형 이름을 포함하여 정규화 된 이름으로 열거자를 사용할 수 없습니다.

enum ESet {a0, a, a1, b1, c3};
enum EAlpha{a, b, c}

select = ESet::a; // error
select = a;       // is ambigious
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.