<CPP>/BASIC

12. 열거형(Enum)

CodeGrimie 2021. 1. 14. 14:55

무조건 연속적으로 정의하는 열거형

▼ 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는 프로그래머의 자유를 조금 줄이는 대신 편리성과 안전성, 그리고 속도 면에서 장점을 가진다.