- 4.7.1 열거형 구현 방식 안 좋은 예
- 4.7.2 Enumerated Types
- 4.7.3 열거형 타입 사용 시 주의사항
4.7.1 열거형 구현 방식 안 좋은 예
어떤 특성에 대해 여러 종류로 분류하는 경우가 굉장히 많다. 실무에서도 입자의 성분을 분류하거나 계산 축을 설정하기 위해 정수형으로 나열해서 쓰곤 했다. 그냥 하드코딩으로 된 것도 있으며, 매크로를 사용하는 경우도 많았다. 아래의 예시를 보자.
int computeDamage(int weapon_id)
{
if (weapon_id == 0) // sword
{
return 1;
}
if (weapon_id == 1) // hammer
{
return 2;
}
// ... 이런식으로 구현하면 힘들어진다.
}
무기별로 데미지를 다르게 해서 구현을 하려 했다. 0을 sword로 생각하고 구현했으며, 주석을 달아서 나름 친절하게 구현을 했다고 볼 수 있겠다. 하지만 무기 특성을 데미지 계산뿐만 아니라 다른 곳에서도 쓴다면 계속 위처럼 조건문을 작성해야 하는데 모든 곳에 주석을 달기엔 비효율적이다.
4.7.2 Enumerated Types
위와 같은 고민을 해결해줄 수 있는 것이 열거형 타입인 enum이 되겠다. 바로 적용된 버전의 코드를 보자.
enum Weapon
{
WEAPON_SWORD,
WEAPON_HAMMER, // 마지막 쉼표 있어도 된다.
};
int computeDamage(int weapon_id)
{
if (weapon_id == WEAPON_SWORD)
{
return 1;
}
if (weapon_id == WEAPON_HAMMER)
{
return 2;
}
// ...
}
아까보다 주석이 줄었으며, 가독성도 좋아졌다. enum의 경우 직접 수치를 입력하지 않을 경우 0부터 1씩 커지는 숫자가 enum 안에 들어간다. 여기서 WEAPON_SWORD가 0이고 다음이 1이 들어가 있다. enum은 헤더에 넣어두고 include하는 방식으로 사용하며, enum 마지막엔 ;으로 끝맺음을 해줘야 한다.
열거형 타입을 반드시 0부터 시작되게 사용하지 않아도 된다. 프로그래머가 값을 입력하면 그 값을 입력한 다음 항목에 대해서는 1씩 증가하게 구현이 된다.
#include <iostream>
#include <typeinfo>
enum Color
{
COLOR_BLACK = -3,
COLOR_RED,
COLOR_BLUE = 5,
COLOR_GREEN,
COLOR_SKYBLUE,
};
int main()
{
using namespace std;
// 초기화 방식은 다른 타입들과 같다.
Color paint = COLOR_BLACK;
Color house(COLOR_BLUE);
Color apple{ COLOR_RED };
Color my_color = COLOR_BLACK;
cout << my_color << " " << COLOR_BLACK << endl;
return 0;
위의 예시는 순서대로 -3, -2, 5, 6, 7이 할당된다. 이처럼 사용자가 할당할 수는 있지만 권장하지 않는 방식이다.
4.7.3 열거형 타입 사용 시 주의사항
하나의 enum에 같은 수를 배정할 수 있지만 의도와는 다르게 작동할 수 있다. 아래의 예시를 수행해보면 조건문이 참으로 되고 두 개가 다른 항목이지만 같다고 판단하는 꼴이 된다.
#include <iostream>
enum Color
{
COLOR_BLACK,
COLOR_RED,
COLOR_BLUE = 5,
COLOR_GREEN = 5,
COLOR_SKYBLUE,
};
int main()
{
using namespace std;
if (COLOR_BLUE == COLOR_GREEN)
cout << "equal" << endl;
return 0;
}
다른 enum일지라도 같은 이름을 가지면 안된다. 아래 예시처럼 int 자료형에도 저장이 가능하기 때문에 같은 이름인 BLUE를 저장할 경우 C2365 에러가 생긴다. 만약 같은 이름을 다른 열거형에서 사용하고싶다면 C++11부터 생긴 enum class를 활용하자.
#include <iostream>
enum Color
{
COLOR_BLACK,
COLOR_RED,
COLOR_BLUE,
COLOR_GREEN,
COLOR_SKYBLUE,
BLUE
};
enum Feeling
{
HAPPY,
JOY,
TIRED,
BLUE,
};
int main()
{
using namespace std;
int color_id = BLUE;
cout << color_id << endl;
return 0;
}
위에서처럼 int 자료형에 enum을 넣는 것은 가능하지만 반대는 안된다. 아래 주석 처리된 부분은 바로 에러가 뜬다. static_cast를 사용하면 넣을 수 있겠지만 애초에 숫자로 넣는 모호한 방식을 사용하지 않기 위해 사용된 것이 열거형이므로 이런 식으로 사용하는 경우는 없을 것으로 생각된다.
enum Color
{
COLOR_BLACK,
COLOR_RED,
COLOR_BLUE,
COLOR_GREEN,
COLOR_SKYBLUE,
};
int main()
{
using namespace std;
int color_id = COLOR_BLUE;
cout << color_id << endl;
// 그냥 넣는건 안된다. 애초에 안그러기 위해 만들어진게 enum
//Color test = color_id;
//Color test = 3;
Color my_color = static_cast<Color>(3);
return 0;
}
cin으로 바로 enum 자료형에 값을 넣는 것은 안된다. 입력 받으려면 우회해야 한다. 입력을 정수로 받고 해당 정수와 enum의 숫자를 일치하는지 조건을 체크하여 구현하는 방법이 최선일 것이다.
#include <iostream>
#include <typeinfo>
enum Color // user-defined data types
{
COLOR_BLACK,
COLOR_RED,
COLOR_BLUE,
COLOR_GREEN,
COLOR_SKYBLUE,
};
int main()
{
using namespace std;
Color my_color = static_cast<Color>(3);
//cin >> my_color;
// 우회하는 방법
int in_number;
cin >> in_number;
if (in_number == 0) my_color = COLOR_BLACK;
// ...
return 0;
}
'Programming Language > C++' 카테고리의 다른 글
Section 8.2. 캡슐화, 접근 지정자, 접근 함수 (0) | 2022.01.19 |
---|---|
Section 8.1. 객체지향 프로그래밍과 클래스 (0) | 2022.01.18 |
Section 4.6. string 문자열 사용 (0) | 2021.11.27 |
Section 4.5. 암시적 형 변환과 명시적 형 변환 (0) | 2021.11.16 |
Section 4.4. using namespace (0) | 2021.11.13 |