---
# System prepended metadata

title: 【C++ 筆記】列舉（Enumeration） - part 34
tags: [程式設計, C++, 程式語言]

---

# 【C++ 筆記】列舉（Enumeration） - part 34

目錄（Table of Contents）：

[TOC]

---

很感謝你點進來這篇文章。

你好，我並不是什麼 C++、程式語言的專家，所以本文若有些錯誤麻煩請各位鞭大力一點，我極需各位的指正及指導！！本系列文章的性質主要以詼諧的口吻，一派輕鬆的態度自學程式語言，如果你喜歡，麻煩留言說聲文章讚讚吧！

## Introduction

列舉（Enumeration），簡稱 Enum，是 C++ 中的一種使用者自定義資料型態（User-Defined Type）。可用於定義一組命名的整數常數，這些常數通常用來表示狀態、選項或模式。

* Enum 有助於為整數值賦予有意義的名稱，以提升程式碼的可讀性與可維護性。 
* 主要適用於我們對某項有少量可能數值（如方向、星期幾等）時。

使用 Enum 的情境大致上有以下這三種（可能更多，只是舉例而已）：

* 方向：東、西、南、北
* 遊戲狀態：選單中、遊戲中、暫停、遊戲結束
* 星期幾：週一到週日

## 定義 enum 與建立一個 enum

在 C++98/03 舊標準中，用關鍵字 `enum` 來定義一個 enum，被稱為「非強型別列舉」或「傳統列舉」。

基本語法：

```cpp=
enum EnumName {
    Value1,
    Value2,
    Value3
};
```

`Value1, Value2, Value3` 等等是常數的名稱，都是唯一的識別字（Identifiers）。預設列舉中第一個名稱會被賦予整數值 0，後續名稱則以 1 遞增。

`Value1 = 0, Value2 = 1, Value3 = 2` 以此類推。

也可以直接手動賦值：

```cpp=
enum EnumName {
    Value1 = v1,
    Value2 = v2,
    Value3 = v3
};
```

v1, v2, v3 的值應為整數。

也不用定義所有常數名稱的值，如果目前常數名稱的值是 x，則後續的值會持續 + 1。

若要建立一個 enum，則要在變數前加上先前定義的 enum 名稱，例如：`EnumName x;`。

也可賦予 enum 內的值作為初始值：`EnumName x = Value1;`。

### 範例 1：星期幾

```cpp=
#include <iostream>

using namespace std;

enum Day{
    SUNDAY,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
};

int main(){
    Day today = WEDNESDAY;
    
    cout << "Today's index is " << today << '\n';
}
```

### 範例 2：東西南北

example from : https://www.geeksforgeeks.org/cpp/enumeration-in-cpp/

```cpp=
#include <iostream>
using namespace std;

// 定義一個 enum 列舉資料型態
// Defining enum
enum direction
{
    EAST,
    NORTH,
    WEST,
    SOUTH
};

int main()
{
    // 建立 enum 變數
    // Creating enum variable
    direction dir = NORTH;

    cout << dir;
    return 0;
}
```

## 強型別列舉（Enum Classes）

C++ 11 引入了這樣的特性，主要彌補先前傳統 `enum` 的兩個缺點：

1. 命名空間汙染（Scope Pollution）：傳統列舉的成員名稱是全域的，因此不能在兩個不同的列舉中使用相同的名稱（如 `enum Color { RED };` 和 `enum Alert { RED };` 會衝突）。
2. 隱式轉換（Implicit Conversion）：傳統列舉會自動轉換成 `int`，可能導致比較錯誤（如拿「顏色」去跟「星期」做比較，編譯器不會報錯）。

C++ 11 引入 Enum Classes 提供安全性更高的型態，也解決上述這些問題。

接下來看看 Enum Classes 的程式怎麼寫吧！

### 範例 3：以 Enum Classes 撰寫的星期幾程式

example from : https://www.geeksforgeeks.org/cpp/enumeration-in-cpp/

在以下的範例中，只要在 `enum` 關鍵字後面再加上一個 `class` 即為 Enum Classes 的撰寫方式。

但需要注意有作用域（Scope）的限制，所以要寫成像這樣的形式去存取 `enum class` 的值：`EnumName::Value`。

在印出 enum 變數時不會自動轉換型態，因此要透過 `static_cast` 去做顯式轉換，才能做下一步的印出動作。

```cpp=
#include <iostream>
using namespace std;

// 定義 enum class
// Define the enum class
enum class Day
{
    Sunday = 1,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
};

int main()
{
    // 初始化
    // initializing
    Day today = Day::Thursday;

    // 印出 enum
    // Print the enum
    cout << static_cast<int>(today);
    
    return 0;
}
```

如果直接印出，寫成像這樣子：`cout << today;` 則會發生以下錯誤：

```
ERROR!
/tmp/h7o8IuG5pb/main.cpp: In function 'int main()':
/tmp/h7o8IuG5pb/main.cpp:25:10: error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'Day')
   25 |     cout << today;
      |     ~~~~ ^~ ~~~~~
      |     |       |
      |     |       Day
      |     std::ostream {aka std::basic_ostream<char>}
In file included from /usr/local/include/c++/14.2.0/iostream:41,
                 from /tmp/h7o8IuG5pb/main.cpp:1:
/usr/local/include/c++/14.2.0/ostream:116:7: note: candidate: 'std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(__ostream_type& (*)(__ostream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; __ostream_type = std::basic_ostream<char>]'
  116 |       operator<<(__ostream_type& (*__pf)(__ostream_type&))
      |       ^~~~~~~~
.
.
.
.
```

然後初始化時也不小心寫成傳統形式 `Day today = Thursday;`，沒有考慮到作用域規則的話，也會產生錯誤：

```
ERROR!
/tmp/286k2LGl0z/main.cpp: In function 'int main()':
/tmp/286k2LGl0z/main.cpp:21:17: error: 'Thursday' was not declared in this scope; did you mean 'Day::Thursday'?
   21 |     Day today = Thursday;
      |                 ^~~~~~~~
      |                 Day::Thursday
/tmp/286k2LGl0z/main.cpp:12:5: note: 'Day::Thursday' declared here
   12 |     Thursday,
      |     ^~~~~~~~
```

### 範例 4：利用運算子重載直接印出

如果覺得顯式轉換太麻煩的話，沒關係！！~~還有更麻煩的寫法~~，讓你直接回到傳統的 enum，一勞永逸的直接把變數 cout 印出來。

```cpp=
#include <iostream>

using namespace std;

enum class Color {
    RED,
    GREEN,
    BLUE
};

ostream& operator<<(std::ostream& os, Color c) {
    switch (c) {
        case Color::RED:   os << "RED";    break;
        case Color::GREEN: os << "GREEN";  break;
        case Color::BLUE:  os << "BLUE";   break;
        default:           os << "UNKNOWN"; break;
    }
    return os;
}

int main() {
    Color myColor = Color::BLUE;

    cout << "My color is: " << myColor;

    return 0;
}
```

### 範例 5：遊戲角色狀態

```cpp=
#include <iostream>
#include <string>

using namespace std;

enum class CharacterState {
    IDLE,       // 閒置
    RUNNING,    // 奔跑
    ATTACKING,  // 攻擊
    DEAD        // 死亡
};

void handleState(CharacterState state) {
    switch (state) {
        case CharacterState::IDLE:
            cout << "[角色] 正在待機，觀察四周..." << endl;
            break;
            
        case CharacterState::RUNNING:
            cout << "[角色] 快速奔跑中！消耗耐力。" << endl;
            break;
            
        case CharacterState::ATTACKING:
            cout << "[角色] 發動攻擊！造成傷害。" << endl;
            break;
            
        case CharacterState::DEAD:
            cout << "[角色] 已死亡。請按 R 重新開始。" << endl;
            break;
            
        default:
            cout << "[系統] 未知狀態錯誤！" << endl;
            break;
    }
}

int main() {
    CharacterState myHero = CharacterState::IDLE;
    handleState(myHero);

    cout << "--- 玩家按下前進鍵 ---" << endl;
    myHero = CharacterState::RUNNING;
    handleState(myHero);

    cout << "--- 玩家遇到敵人 ---" << endl;
    myHero = CharacterState::ATTACKING;
    handleState(myHero);

    cout << "--- 玩家掛機中 ---" << endl;
    myHero = CharacterState::IDLE;
    handleState(myHero);
    
    cout << "--- 玩家被打死了 ---" << endl;
    myHero = CharacterState::DEAD;
    handleState(myHero);

    return 0;
}
```

## 參考資料

[Enumeration in C++ - GeeksforGeeks](https://www.geeksforgeeks.org/cpp/enumeration-in-cpp/)

[C++ 枚举类型详解 | 菜鸟教程](https://www.runoob.com/w3cnote/cpp-enum-intro.html)

[C/C++ enum 用法與範例 | ShengYu Talk](https://shengyu7697.github.io/cpp-enum/)

[列舉](https://openhome.cc/Gossip/CppGossip/enumType.html)