Menu
Coddy logo textTech

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 설계와 잘 통합되어, 코드를 더 읽기 쉽게 만들고 런타임이 아닌 컴파일 타임에 타입 오류를 잡아낼 수 있게 해줍니다.

challenge icon

챌린지

쉬움

열거형 클래스(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: 세 개의 입력을 읽습니다:
    1. 작업 이름 (string)
    2. 정수 형태의 우선순위 레벨 (1=Low, 2=Medium, 3=High, 4=Critical)
    3. 정수 형태의 상태 (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

열거형 클래스가 우선순위와 상태 값을 어떻게 완전히 분리하여 유지하는지 주목하세요. PriorityStatus와 실수로 비교하거나 서로 할당할 수 없습니다. 정수와 열거형 값 사이의 변환에 필요한 명시적인 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;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨