클래스 내에서 열거 형 선언


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.