종종 여러 개의 열거 형이 함께 필요합니다. 때로는 이름 충돌이 있습니다. 이에 대한 두 가지 해결책이 떠 오릅니다. 네임 스페이스를 사용하거나 ‘더 큰’열거 형 요소 이름을 사용하는 것입니다. 그럼에도 불구하고 네임 스페이스 솔루션에는 두 가지 구현이 가능합니다. 하나는 중첩 된 열거 형이있는 더미 클래스 또는 완전한 네임 스페이스입니다.
세 가지 접근 방식의 장단점을 찾고 있습니다.
예:
// oft seen hand-crafted name clash solution
enum eColors { cRed, cColorBlue, cGreen, cYellow, cColorsEnd };
enum eFeelings { cAngry, cFeelingBlue, cHappy, cFeelingsEnd };
void setPenColor( const eColors c ) {
switch (c) {
default: assert(false);
break; case cRed: //...
break; case cColorBlue: //...
//...
}
}
// (ab)using a class as a namespace
class Colors { enum e { cRed, cBlue, cGreen, cYellow, cEnd }; };
class Feelings { enum e { cAngry, cBlue, cHappy, cEnd }; };
void setPenColor( const Colors::e c ) {
switch (c) {
default: assert(false);
break; case Colors::cRed: //...
break; case Colors::cBlue: //...
//...
}
}
// a real namespace?
namespace Colors { enum e { cRed, cBlue, cGreen, cYellow, cEnd }; };
namespace Feelings { enum e { cAngry, cBlue, cHappy, cEnd }; };
void setPenColor( const Colors::e c ) {
switch (c) {
default: assert(false);
break; case Colors::cRed: //...
break; case Colors::cBlue: //...
//...
}
}
답변
원래 C ++ 03 답변 :
(이상 ) 의 이점 은 원할 때 선언 을 사용할 수 있다는 것 입니다.namespace
class
using
를 사용할 때 의 문제namespace
는 네임 스페이스가 코드의 다른 곳에서 확장 될 수 있다는 것입니다. 대규모 프로젝트에서는 두 개의 별개 열거 형이 둘 다 호출되었다고 생각하지 않는다고 보장 할 수 없습니다.eFeelings
더 간단한 코드의 struct
경우 내용이 공개되기를 원하므로를 사용합니다.
이러한 관행 중 하나를 수행하는 경우 곡선보다 앞서 있으므로 더 자세히 조사 할 필요가 없습니다.
최신 C ++ 11 조언 :
C ++ 11 이상을 사용하는 경우 enum class
는 열거 형 이름 내에서 열거 형 값의 범위를 암시 적으로 지정합니다.
이를 통해 enum class
암시 적 변환 및 정수 유형 비교를 잃게되지만 실제로는 모호하거나 버그가있는 코드를 발견하는 데 도움이 될 수 있습니다.
답변
참고로 C ++ 0x에는 언급 한 것과 같은 경우에 대한 새로운 구문이 있습니다 ( C ++ 0x 위키 페이지 참조 ).
enum class eColors { ... };
enum class eFeelings { ... };
답변
나는 다음과 같은 것에 대해 앞의 답변을 혼성화했습니다. (편집 : 이것은 C ++ 11 이전에만 유용합니다. C ++ 11을 사용하는 경우 enum class
)
이 열거 형은 작업자 클래스간에 공유되고 작업자 클래스 자체에 열거 형을 넣는 것은 의미가 없기 때문에 모든 프로젝트 열거 형을 포함하는 하나의 큰 헤더 파일이 있습니다.
는 struct
문법적하고는 : 대중을 방지 typedef
실제로 다른 작업자 클래스 내에서이 열거 형의 변수를 선언 할 수 있습니다.
네임 스페이스를 사용하는 것이 전혀 도움이되지 않는다고 생각합니다. 제가 C # 프로그래머이기 때문일 수 있으며 값을 참조 할 때 열거 형 이름을 사용해야하므로 익숙합니다.
struct KeySource {
typedef enum {
None,
Efuse,
Bbram
} Type;
};
struct Checksum {
typedef enum {
None =0,
MD5 = 1,
SHA1 = 2,
SHA2 = 3
} Type;
};
struct Encryption {
typedef enum {
Undetermined,
None,
AES
} Type;
};
struct File {
typedef enum {
Unknown = 0,
MCS,
MEM,
BIN,
HEX
} Type;
};
…
class Worker {
File::Type fileType;
void DoIt() {
switch(fileType) {
case File::MCS: ... ;
case File::MEM: ... ;
case File::HEX: ... ;
}
}
답변
나는 이것을 위해 클래스를 사용하지 않을 것이다. 대신 네임 스페이스를 사용하십시오. 질문은 네임 스페이스를 사용할 것인지 아니면 열거 형 값에 고유 한 ID를 사용할 것인지로 귀결됩니다. 개인적으로 저는 네임 스페이스를 사용하여 내 ID가 더 짧고 자명 할 수 있기를 바랍니다. 그런 다음 애플리케이션 코드는 ‘using namespace’지시문을 사용하여 모든 것을 더 읽기 쉽게 만들 수 있습니다.
위의 예에서 :
using namespace Colors;
void setPenColor( const e c ) {
switch (c) {
default: assert(false);
break; case cRed: //...
break; case cBlue: //...
//...
}
}
답변
클래스 또는 네임 스페이스 사용의 차이점은 네임 스페이스처럼 클래스를 다시 열 수 없다는 것입니다. 이렇게하면 나중에 네임 스페이스가 남용 될 가능성을 피할 수 있지만 열거 형 집합에도 추가 할 수없는 문제도 있습니다.
클래스 사용의 가능한 이점은 네임 스페이스의 경우가 아닌 템플릿 유형 인수로 사용할 수 있다는 것입니다.
class Colors {
public:
enum TYPE {
Red,
Green,
Blue
};
};
template <typename T> void foo (T t) {
typedef typename T::TYPE EnumType;
// ...
}
개인적으로 저는을 사용 하는 것을 좋아하지 않으며 정규화 된 이름을 선호하므로 네임 스페이스에 대한 플러스로 생각하지 않습니다. 그러나 이것은 아마도 프로젝트에서 내리게 될 가장 중요한 결정은 아닐 것입니다!
답변
클래스 사용의 장점은 그 위에 본격적인 클래스를 구축 할 수 있다는 것입니다.
#include <cassert>
class Color
{
public:
typedef enum
{
Red,
Blue,
Green,
Yellow
} enum_type;
private:
enum_type _val;
public:
Color(enum_type val = Blue)
: _val(val)
{
assert(val <= Yellow);
}
operator enum_type() const
{
return _val;
}
};
void SetPenColor(const Color c)
{
switch (c)
{
case Color::Red:
// ...
break;
}
}
위의 예에서 볼 수 있듯이 클래스를 사용하여 다음을 수행 할 수 있습니다.
- (슬프게도 컴파일 타임이 아닌) C ++에서 잘못된 값에서 캐스트를 허용하지 않습니다.
- 새로 생성 된 열거 형에 대해 (0이 아닌) 기본값을 설정합니다.
- 선택의 문자열 표현을 반환하는 것과 같은 추가 메서드를 추가하십시오.
operator enum_type()
C ++에서 클래스를 기본 열거 형으로 변환하는 방법을 알 수 있도록 선언해야합니다 . 그렇지 않으면 switch
문에 유형을 전달할 수 없습니다 .
답변
열거 형은 둘러싸는 범위로 범위가 지정 되므로 전역 네임 스페이스 오염을 방지하고 이름 충돌을 방지하기 위해 열거 형을 어떤 것으로 래핑하는 것이 가장 좋습니다 . 나는 클래스보다 네임 스페이스를 선호하는 이유 namespace
는 단순히 들고있는 가방처럼 class
느껴지 지만 강력한 객체처럼 느껴 지기 때문입니다 ( struct
비교 class
토론). 네임 스페이스의 가능한 이점은 나중에 확장 할 수 있다는 것입니다. 수정할 수없는 타사 코드를 처리하는 경우 유용합니다.
물론 C ++ 0x로 enum 클래스를 얻을 때 이것은 모두 문제입니다.