강께르의 개발일지
[C++] enum과 enum class 본문
이 글에서 서술한 열거형은 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
};
'프로그래밍 > C++' 카테고리의 다른 글
[C++] 포인터 변수의 const 사용에 대해 (0) | 2021.06.13 |
---|---|
[C++] 객체 지향 프로그래밍과 특징 정리 (0) | 2021.06.10 |
[C++] void 포인터와 함수형 포인터 (0) | 2021.06.10 |
[C++] Call by value / address / reference (0) | 2021.06.09 |
[C++] 함수 / 함수 오버로딩 / 디폴트 매개변수 (0) | 2021.06.07 |