클래스 내에서 열거 형 선언


151

다음 코드 스 니펫에서 Color열거 형 Car의 범위를 제한하고 전역 네임 스페이스를 "폴링"하지 않도록 클래스 내 에서 열거 형이 선언됩니다 .

class Car
{
public:

   enum Color
   {
      RED,
      BLUE,
      WHITE
   };

   void SetColor( Car::Color color )
   {
      _color = color;
   }

   Car::Color GetColor() const
   {
      return _color;
   }

private:

   Car::Color _color;

};

(1) 이것이 Color열거 의 범위를 제한하는 좋은 방법 입니까? 또는 Car클래스 외부에서 선언해야 하지만 자체 네임 스페이스 또는 구조체 내에서 선언해야 합니까? 나는 오늘이 기사를 보았습니다.이 기사는 후자를 옹호하고 열거 형에 대한 몇 가지 좋은 점을 논의합니다 : http://gamesfromwithin.com/stupid-c-tricks-2-better-enums .

작업 할 때이 예에서 (2) 내에서 클래스, 그것은뿐만 코드에 가장 열거입니다 Car::Color, 아니면 그냥 것 Color충분? ( Color글로벌 네임 스페이스에 선언 된 또 다른 열거 형 이있는 경우를 대비하여 전자가 더 낫다고 가정합니다 . 적어도 우리는 참조하는 열거 형에 대해 명시 적입니다.)

답변:


86
  1. 경우 Color단지에 특정 뭔가 Car당신이 그 범위를 제한 할 방법입니다 그 후들. Color다른 클래스가 사용하는 다른 열거 형을 사용하려는 경우 전역 (또는 적어도 외부 Car)으로 만들 수도 있습니다 .

  2. 차이가 없습니다. 전역이있는 경우 현재 범위에 가까워 지므로 여전히 로컬이 사용됩니다. 클래스 정의 외부에서 해당 함수를 정의 Car::Color하면 함수의 인터페이스에서 명시 적으로 지정해야합니다 .


12
2. 그렇습니다. Car::Color getColor()하지만 이미 지정자가 void Car::setColor(Color c)있기 때문입니다 setColor.
Matthieu M.


66

나는 다음과 같은 접근 방식을 선호합니다 (아래 코드). "네임 스페이스 오염"문제를 해결하지만 훨씬 안전합니다 (두 개의 다른 열거 형을 할당하거나 비교할 수 없으며 다른 내장형과 같은 열거 형도 비교할 수 없습니다).

struct Color
{
    enum Type
    {
        Red, Green, Black
    };
    Type t_;
    Color(Type t) : t_(t) {}
    operator Type () const {return t_;}
private:
   //prevent automatic conversion for any other built-in types such as bool, int, etc
   template<typename T>
    operator T () const;
};

용법:

Color c = Color::Red;
switch(c)
{
   case Color::Red:
     //некоторый код
   break;
}
Color2 c2 = Color2::Green;
c2 = c; //error
c2 = 3; //error
if (c2 == Color::Red ) {} //error
If (c2) {} error

사용법을 쉽게하기 위해 매크로를 만듭니다.

#define DEFINE_SIMPLE_ENUM(EnumName, seq) \
struct EnumName {\
   enum type \
   { \
      BOOST_PP_SEQ_FOR_EACH_I(DEFINE_SIMPLE_ENUM_VAL, EnumName, seq)\
   }; \
   type v; \
   EnumName(type v) : v(v) {} \
   operator type() const {return v;} \
private: \
    template<typename T> \
    operator T () const;};\

#define DEFINE_SIMPLE_ENUM_VAL(r, data, i, record) \
    BOOST_PP_TUPLE_ELEM(2, 0, record) = BOOST_PP_TUPLE_ELEM(2, 1, record),

용법:

DEFINE_SIMPLE_ENUM(Color,
             ((Red, 1))
             ((Green, 3))
             )

일부 참고 문헌 :

  1. Herb Sutter, 점 Hyslop, C / C ++ 사용자 저널, 22 (5), 2004 년 5 월
  2. Herb Sutter, David E. Miller, Bjarne Stroustrup Strongly Typed Enums (개정 3), 2007 년 7 월

나는 이것을 좋아한다. 또한 열거 형이 유효한 값으로 인스턴스화되도록합니다. 할당 연산자와 복사 생성자가 유용하다고 생각합니다. 또한 t_는 개인용이어야합니다. 내가없이 할 수있는 매크로.
jmucchiello

나도 이걸 좋아해 참조 주셔서 감사합니다.
anio

1
당신은 말했다 : "또한 더 많은 형태 보증 당신이 할당 할 수 없습니다 심지어 두 개의 서로 다른 열거 비교 (이다 ..." 왜 내가 생각하는 그것이 좋은 기능입니다 생각 하는가.? if(c2 == Color::Red )합리적이고 컴파일해야하지만, 귀하의 예제에서 과제에 대한 동일한 주장
Nawaz

3
@Nawaz c2는 다른 유형 ( Color2)이므로 c2 == Color::Red과제를 컴파일해야하는 이유는 무엇입니까? Color::Red1이면 Color2::Red2 이면 어떻게 되나요? 또는로 Color::Red == Color2::Red평가 해야합니까 ? 형식이 안전한 열거자를 혼합하면 시간이 나쁠 것입니다. truefalse
Victor K

2
왜 t_ 타입이 아닌가; 은밀한?
Zingam

7

일반적으로 항상 열거 형을에 넣습니다 struct. "접두사"를 포함한 여러 지침을 보았습니다.

enum Color
{
  Clr_Red,
  Clr_Yellow,
  Clr_Blue,
};

항상 이것이 C지침보다 지침 과 비슷하다고 생각했습니다 C++(약어 및 네임 스페이스 때문 C++).

따라서 범위를 제한하기 위해 이제 두 가지 대안이 있습니다.

  • 네임 스페이스
  • 구조체 / 클래스

struct네임 스페이스를 조작 할 수없는 동안 템플릿 프로그래밍을위한 매개 변수로 사용할 수 있기 때문에 개인적으로 사용하는 경향이 있습니다 .

조작의 예는 다음과 같습니다.

template <class T>
size_t number() { /**/ }

struct 내부의 열거 형 요소 수를 반환합니다. T:)


3

코드 라이브러리를 만드는 경우 네임 스페이스를 사용합니다. 그러나 해당 네임 스페이스에는 여전히 하나의 Color 열거 형 만있을 수 있습니다. 공통 이름을 사용할 수 있지만 클래스마다 다른 상수를 가질 수있는 열거 형이 필요한 경우 접근 방식을 사용하십시오.

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