12. 열거형(Enum)
무조건 연속적으로 정의하는 열거형
▼ enum 예시
enum class CharacterState
{
IDLE = 0,
WALK,
RUN,
JUMP,
ATTACK
};
CPP에는 열거형에는 Enum과 Enum Class 가 있다.
Enum Class는 CPP 11에서 추가된 기능으로 Enum의 기능에서 namespace의 기능을 더한 것이라고 한다.
즉 enum들끼리 보다 정확하게 구분 짓는데 도움을 줍니다.
정확한 예시를 위해 아래의 코드를 살펴보자.
▼ 기존 enum의 namespace 문제
enum RAINBOW_COLOR{
RED,
ORANGE,
YELLLOW,
GREEN,
BLUE,
INDIGO,
PURPLE
};
enum COLOR{
RED
};
int main()
{
int color = RED; // ERROR
return (0);
}
아주 치명적인 코드다.
Main 함수에서 color가 RAINBOW_COLOR의 RED인지 COLOR의 RED인지 정확하게 알 수 없다.
심지어 컴파일러 조차도 어떤 RED를 말하는 것인지 알지 못해서 최근 컴파일러들은 재정의(Redefine)되었다고 에러를 발생한다.
이 문제를 해결하기 위해서 기존의 enum은 다른 enum과 구분 짓기 위해서 변수명에 별도의 식별 문자를 붙이곤 한다.
▼ enum의 식별문자
enum RAINBOW_COLOR {
rRED,
rORANGE,
rYELLLOW,
rGREEN,
rBLUE,
rINDIGO,
rPURPLE
};
enum COLOR {
RED
};
int main()
{
int color = rRED;
return (0);
}
Rainbow의 앞글자 r을 붙임으로써 일단 COLOR의 RED와 구분된다.
이 식별 문자를 설정하는 기준은 프로그래머, 팀, 프로젝트마다 다 다르다. 중요한 건 식별 문자를 입력해서 구분해야 한다는 번거로움이 있다는 것이다.
혹은 CPP 한해서 아예 namespace를 설정해서 구분하는 방법도 있었다.
▼ enum과 namespace 예제
namespace RAINBOW {
enum COLOR {
RED,
ORANGE,
YELLLOW,
GREEN,
BLUE,
INDIGO,
PURPLE
};
}
enum COLOR {
RED
};
int main()
{
int color = RAINBOW::RED;
return (0);
}
밑의 COLOR와 명확하게 구분되고 내부 변수명 또한 추가적인 식별 문자를 더할 필요가 없다.
이것만으로도 충분하게 구분되지만 CPP 표준위원회는 좀 더 보안적인 부분을 강화하기로 한다.
Enum Class는 좀 더 깐깐한 열거형이다.
그런 상태에서 좀 더 보안에 좋고 사용하기 편한 enum class가 만들어진다.
▼enum class의 보장된 namespace
enum class RAINBOW_COLOR {
RED,
ORANGE,
YELLLOW,
GREEN,
BLUE,
INDIGO,
PURPLE
};
enum class COLOR {
RED
};
int main()
{
int color = static_cast<int>(RAINBOW_COLOR::RED);
return (0);
}
namespace를 설정한 것처럼 구분되는 것을 볼 수 있다.
그리고 암묵적으로 int로 변환이 되지 않기 때문에 명시적 형 변환을 사용해 일어날 수 있는 실수들을 미연에 방지한다.
특히 enum class의 강력한 장점은 전방 선언이 된다는 것에 있다.
▼enum class의 전방 선언
enum class E : int;
void Foo(E e);
enum class E {A, B, C};
CPP 레퍼런스 문서에 적혀있는 문법이지만 안타깝게도 현재 테스트 중인 코드에서는 에러가 발생했다.
20210114 수정
CPP 페이스북 커뮤니티에서 고수들의 피드백을 받을 수 있었다.
Enum Class의 전방 선언은 실제로 내부 값을 쓰지 않을 때 사용할 수 있다고 한다.
위의 코드 예시 처럼 함수의 매개 변수를 지정할 때 사용하는 것이라고 한다.
Enum Class는 프로그래머의 자유를 조금 줄이는 대신 편리성과 안전성, 그리고 속도 면에서 장점을 가진다.