C++

<C++> enum class

hanseongbugi 2024. 4. 4. 17:55

enum class?

  • enum class는 C++11에서 enum 자료형의 단점을 보안하기 위해 도입된 것이다.
    • enum의 문제점은 enum은 별도의 이름공간(namespace)를 가지고 있지 않는 것
  • 간단히 이야기하면 enum 들을 정확하게 구분하기 위해서 enum class가 도입된 것

기존 enum의 문법

#include<iostream>
using namespace std;

enum ECar{
    BMW,
    AUDI,
    KIA,
    BENZ,
    HYUNDAE,
    PORSCHE,
};

enum EKoreaCar{
    KIA,
    HYUNDAE,
};

int main(void)
{
    int num = KIA; //error
    cout << "KIA : " << num << endl;
    return 0;
}
  • KIA, HYUNDAE 처럼 열거자 이름들이 중복 되는 경우들이 있을 수 있다.
  • 이런경우 컴파일러가 ECar의 KIA인지 EKoreaCar의 KIA인지 알 수가 없다.
  • 결론적으로 기존의 enum은 저런식으로 enum의 열거자 이름들을 중복해서 사용할 수 없다.

enum의 이름이 중복되지 않게 접두, 접미를 넣어서 사용

#include<iostream>
using namespace std;
enum ECar{
    cBMW,
    cAUDI,
    cKIA,
    cBENZ,
    cHYUNDAE,
    cPORSCHE,
};

enum EKoreaCar{
    kcKIA,
    kcHYUNDAE,
};

int main(void)
{
    int num = cKIA;
    cout << "KIA : " << num << endl;
    return 0;
}

이름이 중복되는 enum이 생길경우 별도의 namespace를 만들어서 사용

#include<iostream>
using namespace std;

namespace TYPEA{
    enum ECar{
        BMW,
        AUDI,
        KIA,
        BENZ,
        HYUNDAE,
        PORSCHE,
    };
}

namespace TYPEB{
    enum EKoreaCar{
        KIA,
        HYUNDAE,
    };
}


int main(void)
{
    int num = TYPEA::KIA;
    cout << "KIA : " << num << endl;
    return 0;
}
  • 위에서 소개한 2가지 방식으로 enum을 구분해서 사용할 수 있다.
  • 하지만 enum class가 나온 후 위 방식을 사용하지 않아도 된다.

enum class 사용법

enum class [열거형이름]
{
	//..열거자..
}
  • enum뒤에 class만 붙여주면 enum class를 선언할 수 있다.
  • 호출 시 열거형이름::열거자의 형태로 호출할 수 있다.
enum class EColor
{
	RED,
	BLUE,
	GREEN,
	YELLOW,
}

enum class ERainbowColor
{
	RED,
	ORANGE,
}

// 사용법
EColor::RED
ERainbowColor::RED
  • 하지만 enum class는 enum과 다르게 주의할 점이 생기게되었다.

enum class 사용 시 주의할 점

열거자 이름에 의한 중복이 없다

  • enum class는 enum과 달리 enum에 이름공간을 지어준다.
  • 그렇기 때문에 코드를 작성할때 좀더 편리하고 정확하게 enum을 사용할 수 있다.

타입 변환에 좀 더 까다로움

#include<iostream>
using namespace std;
enum ESubject{
    MATH,
    KOREAN,
    ENGLISH,
};

int main(void)
{
    if(KOREAN == 1) {
        cout << "KOREAN is 1" << endl;
    }
    else {
        cout << "KOREAN is not 1" << endl;
    }
    
    return 0;
}
  • 기존의 enum은 int값으로 형변환 되어 위 코드와 같은 작업을 할 수 있었다.
  • enum 값이 암시적으로 형변환되어 int와 비교가 가능한 것은 이점처럼 보이지만 프롤그래머에게 예상치 못한 에러를 초래할 수 있다.
  • enum class를 사용하면 더이상 int 값으로 암시적 형변환이 일어나지 않는다.
#include<iostream>
using namespace std;
enum class ESubject{
    MATH,
    KOREAN,
    ENGLISH,
};

int main(void)
{
		// static_cast 를 이용해서 int 타입으로 형변환.
		// 이름공간(ESubject::)을 통해서 KOREAN 에 접근합니다. 

    if(static_cast<int>(ESubject::KOREAN) == 1) {
        cout << "KOREAN is 1" << endl;
    }
    else {
        cout << "KOREAN is not 1" << endl;
    }
    
    return 0;
}
  • enum class를 사용하면 명시적 형변환을 통해 열거자를 비교해야한다.

전방 선언 가능

  • 전방선언(forward declaration)은 선언을 먼저하고 정의를 나중에 해도 된다는 것
#include<iostream>
using namespace std;
enum class ESubject : int; //전방선언

int main(void)
{
		//선언한걸 사용
    if(static_cast<int>(ESubject::KOREAN) == 1) {
        cout << "KOREAN is 1" << endl;
    }
    else {
        cout << "KOREAN is not 1" << endl;
    }
    
    return 0;
}

//enum class정의
enum class ESubject : int
{
    MATH,
    KOREAN,
    ENGLISH,
};
  • enum class를 선방 선언 시 데이터 타입을 지정해 주어야 한다.
  • 뒤에 데이터 타입을 지정하는 것은 바탕 형식을 지정하는 것 혹은 타입 선언을 하는 것이라고 한다.
  • 컴파일러가 미리 선언을 통해서 메모리를 잡고 있어야 하기 때문에 바탕형식(어떤 타입으로 enum을 사용할건지) 지정 해야한다.

 

 

 

출처

https://blockdmask.tistory.com/405

 

[C++] enum class (scoped enum) 에 대해서

안녕하세요. BlockDMask 입니다. 오늘은 C++11에서 추가된 enum class에 대해서 알아볼까 합니다.지금이 2020년도이니, 이미 당연스러운 C++ 문법이라고 생각하실 수도 있겠네요.enum이랑 enum class가 무엇이

blockdmask.tistory.com