본문 바로가기

[C++] enum class 사용하기

Kwonriver 2022. 1. 22.
728x90

일반적으로 중괄호 안에서 선언된 변수 등은 중괄호 안에서만 효력을 발휘한다.

전역에서 선언된 것들이 아닌 로컬영역에서 선언된 것들이 그런 것들이다.

 

 

위 처럼 test 함수의 로컬 영역에서 선언된 test는 그 범위를 벗어나는 순간 없는 것으로 판단된다.

따라서 main 함수 안에서 또 다시 test를 선언하고 사용할 수 있다.

 

그런데 enum의 경우 좀 다르다.

이렇듯 enum은 중괄호 범위 밖에서도 사용이 가능하다.

이를 공식적으로 unscoped enum 이라 한다. ( 이하 범위 없는 enum )

이와 반대되는 개념으로 C++11에 도입된 scoped enum 이 존재한다 ( 이하 범위 있는 enum )

 

바로 enum클래스 이다.

범위 있는 enum은 중괄호의 범위가 효력을 발휘하게 된다

위 사진처럼 int color 에 RED를 넣을 수 없음을 볼 수 있다.

 

범위 있는 enum의 강점 중 하나는 열거자들의 자료형에 강력하게 적용된다는 것이다.

범위 없는 enum의 열거자들은 암묵적으로 정수로 형변환 된다.

따라서 저절로 int 형으로 변환된다

그림 1에서 볼 수 있듯이 enum의 자료형을 알 수 없음에도 불구하고 int 형인 color에 너무나 자연스럽게 대입이된다.

그러나 범위 있는 enum의 경우 그림 2에서 처럼 int형 red에 Color::RED를 대입할 수 없다.

 

어떠한 이유에서 다른 자료형으로 변환하기 위해서는 캐스팅 연산자를 사용해야한다.

static_cast<double>(color) 이런 식으로 말이다.

 

또 다른 장점은 범위 있는 enum은 전방선언이 가능하다는 것이다.

전방선언은 함수등을 선언만 하고 본체는 나중에 정의하는 것을 의미한다.

 

그런데 사실 C++11 부터는 범위 없는 enum도 전방선언이 가능하다.

문법상 오류가 없는 것이다.

 

그렇다면 왜 전방선언이 가능할까?

enum의 경우 컴파일러가 바탕형식(underlying type)을 결정한다.

그런데 이 때 범위 없는 enum의 경우 정수형으로 결정해버리기 때문에 전방선언이 가능하다.

 

 

이러한 enum이 있다고 할 때 컴파일러는 바탕형식으로 char를 선택할 것이다.

RED = 0으로 시작할 것이기 때문에 아무리 해도 127을 넘지 않는다.

 

그런데 다음과 같은 enum은 어떡할까

 

 

이미 char의 최고값인 127을 넘어서는 값이 존재한다.

32비트 char을 쓰는 컴퓨터는 거의 없으므로 컴파일러는 이보다 큰 정수형식을 선택하게 된다.

메모리의 효율을 위해서 컴파일러는 주어진 열거자를 감당할 수 있는 가장 작은 자료형을 선택하게 된다.

그러나 경우에 따라서 크기 대신 속도를 중요시하여 다르게 선택할 수도 있다.

 

enum을 전방 선언을 하지 않게 되면 나타나는 문제점이 있다.

바로 컴파일 의존 관계가 늘어난다는 것인데 이는 다음과 같다.

 

위 사진의 Test를 가지고 컴파일을 완료했다

그런데 추가할 부분이 생겨서 다음과 같이 추가하였다.

 

이런 경우 시스템 전체를 다시 컴파일 해야한다.

이 enum을 많이 사용하지 않는다 하더라도 전체를 재컴파일 해야한다.

이는 말도 안되는 일이 아닐 수 없다.

 

그러나 C++11 부터 제공되는 enum의 전방선언으로 방지할 수 있게 되었다.

 

에러가 없음을 알 수 있다.

이런 식의 사용은 enum에 새로운 열거자가 추가된다 하더라도 시스템을 다시 컴파일할 필요가 없고

testFunc의 행동에 영향을 미치지 않는다면 testFunc를 재컴파일 할 필요가 없다.

 

그런데 전방선언을 하기 위해서 크기를 알아야 한다.

그렇다면 컴파일러는 어떻게 enum의 크기를 아는 걸까?

 

범위있는 enum의 바탕형식은 컴파일러는 어떠한 경우에서도 알아낼 수 있으며,

범위 없는 enum의 바탕형식은 사용자가 직접 정의할 수 있다.

또한 범위 있는 enum의 바탕형식은 기본적으로 int이다.

 

바탕형식을 바꾸기 위해서는 다음과 같이 명시적으로 지정한다.

 

 

범위 없는 enum의 바탕형식 변경도 위와 같으며 enum의 정의에서도 마찬가지로 사용하면 된다.

 

728x90