Enum 클래스와 강력한 타이핑
Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 104개 중 80번째.
C++11은 기존 C 스타일 enums의 단점을 해결하기 위해 enum classes(범위가 지정된 열거형이라고도 함)를 도입했습니다. 이들은 더 강력한 타입 안전성을 제공하며 열거형 값의 실수로 인한 오용을 방지합니다.
전통적인 열거형(enum)에는 문제가 있습니다. 열거형의 값들이 주변 스코프로 유출되고 정수로 암시적 변환되어, 미묘한 버그를 유발할 수 있습니다:
// 전통적인 열거형 - 문제 발생 가능
enum Color { Red, Green, Blue };
enum TrafficLight { Red, Yellow, Green }; // 오류! Red와 Green이 이미 정의됨
int x = Red; // int(0)로 암시적 변환됨
if (Red == 0) { } // 컴파일됨 - 열거형과 정수 비교열거형 클래스(Enum classes)는 값의 범위를 제한하고 암시적 변환을 방지함으로써 이러한 문제들을 해결합니다:
enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green }; // OK - 충돌 없음
Color c = Color::Red; // 반드시 범위 지정 연산자를 사용해야 함
// int x = c; // 오류! 암시적 변환 없음
int x = static_cast<int>(c); // 명시적 변환 필요
// if (c == 0) { } // 오류! int와 비교할 수 없음
if (c == Color::Red) { } // OK - 동일한 타입 비교메모리 제어를 위해 기본 타입을 지정할 수도 있습니다:
enum class Status : uint8_t {
Inactive = 0,
Active = 1,
Pending = 2
};Enum 클래스는 OOP 설계와 잘 통합되어, 코드를 더 읽기 쉽게 만들고 런타임이 아닌 컴파일 타임에 타입 오류를 잡아낼 수 있게 해줍니다.
챌린지
쉬움열거형 클래스(enum classes)를 사용하여 다양한 우선순위 레벨과 작업 상태를 나타내는 작업 우선순위 시스템을 구축해 보겠습니다. 이를 통해 열거형 클래스가 어떻게 타입 안전성을 제공하고 기존 열거형에서 발생하는 버그를 방지하는지 확인할 수 있습니다.
코드는 다음 세 개의 파일로 구성됩니다:
TaskTypes.h: 작업 시스템을 위한 열거형 클래스를 정의합니다.Low,Medium,High,Critical값을 가지는Priority열거형 클래스를 생성하세요. 기본 타입을int로 지정하고, 각 값은 순서대로 1, 2, 3, 4가 되도록 합니다.Pending,InProgress,Completed값을 가지는Status열거형 클래스를 생성하세요.두 개의 헬퍼 함수를 제공합니다:
priorityToString(Priority p)— 우선순위를 문자열("Low", "Medium", "High", 또는 "Critical")로 반환합니다.statusToString(Status s)— 상태를 문자열("Pending", "InProgress", 또는 "Completed")로 반환합니다.
Task.h: 정의한 열거형 클래스를 사용하는Task클래스를 정의합니다.Task클래스는 이름(string),Priority,Status를 저장해야 합니다. 생성자는 이름과 우선순위를 매개변수로 받으며, 상태는 기본적으로Status::Pending으로 설정됩니다.다음 메서드들을 구현하세요:
setStatus(Status s)— 작업의 상태를 업데이트합니다.getPriorityValue()—static_cast를 사용하여 우선순위의 내부 정수 값을 반환합니다.display()— 작업을 다음 형식으로 출력합니다:[name] - Priority: [priority] (Value: [value]) - Status: [status]
main.cpp: 세 개의 입력을 읽습니다:- 작업 이름 (string)
- 정수 형태의 우선순위 레벨 (1=Low, 2=Medium, 3=High, 4=Critical)
- 정수 형태의 상태 (0=Pending, 1=InProgress, 2=Completed)
주어진 이름과 우선순위로
Task객체를 생성합니다 (정수를static_cast를 사용하여 적절한Priority열거형 값으로 변환하세요). 그런 다음 세 번째 입력을 기반으로 상태를 설정합니다. 마지막으로display()를 호출하여 작업 상세 내용을 표시합니다.
예를 들어, 입력이 Fix bug, 3, 1인 경우:
Fix bug - Priority: High (Value: 3) - Status: InProgress입력이 Write docs, 1, 2인 경우:
Write docs - Priority: Low (Value: 1) - Status: Completed입력이 Deploy app, 4, 0인 경우:
Deploy app - Priority: Critical (Value: 4) - Status: Pending열거형 클래스가 우선순위와 상태 값을 어떻게 완전히 분리하여 유지하는지 주목하세요. Priority를 Status와 실수로 비교하거나 서로 할당할 수 없습니다. 정수와 열거형 값 사이의 변환에 필요한 명시적인 static_cast는 코드의 의도를 명확하게 하고 미묘한 버그를 방지합니다.
치트 시트
C++11은 기존의 C 스타일 열거형(enum)보다 더 강력한 타입 안전성을 제공하기 위해 enum 클래스(범위가 지정된 열거형, scoped enumerations)를 도입했습니다.
기존의 열거형은 범위 누수(scope leakage)와 암시적 변환(implicit conversions)과 관련된 문제점이 있습니다:
// 기존 열거형 - 문제 발생 가능
enum Color { Red, Green, Blue };
enum TrafficLight { Red, Yellow, Green }; // 오류! Red와 Green이 이미 정의됨
int x = Red; // 암시적으로 int로 변환됨
if (Red == 0) { } // 컴파일됨 - 열거형과 int를 비교Enum 클래스는 범위 지정(scope resolution)을 요구하고 암시적 변환을 방지함으로써 이러한 문제들을 해결합니다:
enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green }; // OK - 충돌 없음
Color c = Color::Red; // 반드시 범위 지정 연산자를 사용해야 함
// int x = c; // 오류! 암시적 변환 불가
int x = static_cast<int>(c); // 명시적 변환 필요
// if (c == 0) { } // 오류! int와 비교할 수 없음
if (c == Color::Red) { } // OK - 동일한 타입끼리 비교메모리 제어를 위해 기저 타입(underlying type)을 지정할 수 있습니다:
enum class Status : uint8_t {
Inactive = 0,
Active = 1,
Pending = 2
};Enum 클래스와 정수 사이의 변환을 위해서는 명시적 캐스팅(explicit casting)을 사용하세요:
// 정수를 enum 클래스로 변환
Priority p = static_cast<Priority>(3);
// enum 클래스를 정수로 변환
int value = static_cast<int>(p);직접 해보기
#include <iostream>
#include <string>
#include "Task.h"
using namespace std;
int main() {
// 입력 읽기
string taskName;
int priorityInt;
int statusInt;
getline(cin, taskName);
cin >> priorityInt;
cin >> statusInt;
// TODO: 주어진 이름과 우선순위로 Task 생성
// static_cast를 사용하여 priorityInt를 Priority 열거형으로 변환
// TODO: statusInt를 기반으로 작업의 상태 설정
// static_cast를 사용하여 statusInt를 Status 열거형으로 변환
// TODO: display()를 호출하여 작업 상세 정보 표시
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.