강께르의 개발일지

[C++] enum과 enum class 본문

프로그래밍/C++

[C++] enum과 enum class

강께르 2021. 6. 10. 21:12

 이 글에서 서술한 열거형은 C 스타일로 enum, C++ 스타일로 enum class로 나눌 수 있다. 열거형이 무엇이며, enum과 enum class의 다른 점이 무엇인지 조사하며 정리해보려고 한다.

 

1. 열거형이란?

- 열거형의 '열거'의 의미는 '여러 가지 예나 사실을 낱낱이 죽 늘어놓음'이라고 한다. 이와 같이 열거형 또한 정수형 집합을 고유한 이름을 붙여서 죽 늘어놓은 것을 의미한다.

- 특정 정수값에 별명을 붙여 프로그래머가 봤을 때, 해당 정수가 사용된 의미에 대해 직관적으로 이해할 수 있게 돕는 도구와 같은 것이다.

 

2. enum

- 열거형을 사용하기 위해서는 enum이나 enum class를 사용해야 한다. enum의 생김새는 다음과 같다

enum TagName { Body };

- 열거형을 사용하기 위해서 열거형을 정의해야한다. 열거형을 정의하기 위해서 enum을 앞에 타이핑을 한다.

- TagName은 열거형의 이름을 이야기한다. 열거형의 이름은 없어도 정의할 수 있다. 하지만 열거형 변수로 선언하여 사용하지 못한다. 다만 별명만 꺼내서 쓸 수 있다.

- Body에는 그 별명들과 별명의 값이 있다. 여기서 별명을 지칭하는 말로 열거자라고 한다. 특정 이름을 나열하면 따로 정수를 지정하지 않아도 나열한 순서대로 컴파일러가 각 이름들 순서대로 0부터 값을 준다. 특정 정수값으로 열거형의 값을 지정하고프면 지정하고자 하는 열거자 하나를 골라 값을 대입해주면 된다.

enum COLOR {
    RED, // 값은 0
    BLUE = 3,
    GREEN = 5
}; // color

- 위는 예로 든 코드이다. 이 열거형의 이름은 COLOR이고 그 열거자들로 RED, BLUE, GREEN을 갖는다.

- 각 값은 다음과 같다. RED는 따로 설정하지 않은 첫 값이므로 0이다. BLUE와 GREEN는 대입된 값인 3, 5을 갖는다.

- 열거형 선언 시 닫는 괄호 뒤에 이름을 써놓는다면 그것은 열거형 변수를 그 이름으로 선언하는 것이다.

COLOR color = COLOR::RED;

switch(color)
{
case COLOR::RED:
        break;
case BLUE:
	break;
case COLOR::GREEN:
	break;
}

- 위와 같은 코드로 열거형은 정수를 필요로 하는 switch문과 주로 같이 묶인다. COLOR형 변수 color가 switch문의 조건의 정수로 사용되고 그에 맞는 결과를 COLOR에 정의한 열거자로 구분할 수 있어 가독성이 좋다.

- 여기서 볼 것은 BLUE는 COLOR::와 같은 열거형 타입과 범위 지정 연산자를 쓰지 않았는데 이래도 사용 가능하다.

 

3. enum의 문제

- 그렇다면 멀쩡히 있는 enum을 두고 enum class는 왜 C++11에 추가되었을까?

- enum은 자주 사용하는 정수에 이름을 붙이는 개념이니, 많은 enum을 사용한다고 가정했을 때 이러한 사용 방식은 안전하지 않거나 프로그래머 입장에서 이해되지 않을 수 있다는 것이다.

enum ACTION {
    EAT,
    SLEEP,
    STUDY
};

enum GENRE {
    HORROR,
    THRILL,
    ROMANCE
};

ACTION action = ACTION::EAT;
GENRE genre = GENRE::HORROR;

if (action == genre)
...

- 서로 다른 열거형 변수의 비교는 상식적으로 같다고 판단하지 않길 바란다. 하지만 컴파일러가 이 둘을 비교할 때, 정수로 형 변환을 하여 정수비교를 한다. 그렇기에 서로 다른 열거형의 두 변수는 같은 값을 같고 있다고 판단할 것이다!

 

4. enum class

- 그럼 enum이 enum class와 다른 점은 무엇인가?

enum class COLOR {
	RED, // 값은 0
	BLUE = 3,
	GREEN = 5
}; // color

enum class GENRE {
	HORROR,
	THRILL,
	ROMANCE
};

COLOR color = COLOR::RED;

if (COLOR::RED == GENRE::HORROR) { } // 오류! 더이상 정수승급 비교 X

switch (color)
{
case COLOR::RED:
	break;
case BLUE:	// 오류! 범위지정연산자 사용해야한다
	break;
case COLOR::GREEN:
	break;
}

- 선언은 enum으로 입력했던 자리에 enum class라고 적어주면 된다.

- 더 이상 다른 열거형과의 비교와 더불어 다른 자료형과의 비교, 특히 정수형 비교가 불가능하다. 오로지 같은 열거형 비교만 허용되어 남용, 오용을 방지한다.

- enum에서는 열거자만 쓸 수 있었으나, enum class는 어떤 열거형 변수의 열거자인지 범위지정 연산자와 함께 써야한다.

 

추가)

- 열거형의 이름 뒤에 : (자료형) 을 사용함으로 열거형의 열거자가 각각 어떤 자료형을 갖는지 정할 수 있다.

enum class COLOR : int
{
    RED,
    BLUE,
    GREEN
};