06_switch文と列挙型(enum class)

はじめに

この章では、複数の選択肢から1つを選んで処理を分ける switch 文と、C++における列挙型(enum class)について学びます。あわせて、enum class を扱うために必要な型変換static_cast)も先に整理します。

switch文の基本的な使い方

#include <iostream>
using namespace std;

int main() {
    int level;
    cout << "レベル(1〜3)を入力:";
    cin >> level;

    switch (level) {
        case 1:
            cout << "初級です。" << endl;
            break;
        case 2:
            cout << "中級です。" << endl;
            break;
        case 3:
            cout << "上級です。" << endl;
            break;
        default:
            cout << "範囲外です。" << endl;
            break;
    }
    return 0;
}
注意:break を忘れるとフォールスルーが起きる
break; がないと、マッチした case 以降のすべての case が続けて実行されてしまいます。必ず書くようにしましょう。

C言語スタイルの enum の使い方

#include <iostream>
using namespace std;

enum Rank { Gold = 1, Silver, Bronze };

int main() {
    Rank rank = Silver;

    switch (rank) {
        case Gold:
            cout << "金賞" << endl;
            break;
        case Silver:
            cout << "銀賞" << endl;
            break;
        case Bronze:
            cout << "銅賞" << endl;
            break;
        default:
            cout << "参加賞" << endl;
            break;
    }
    return 0;
}

C++の列挙型:enum class

C++には enum class という列挙型が用意されています。型の安全性と大規模開発でのミス防止を重視した設計です。

通常の enum と enum class の違い

比較項目 通常の enum enum class
定数の書き方 Gold Rank::Gold
名前の漏れ グローバルに展開される スコープ内に閉じている
整数への変換 自動変換される 明示的なキャストが必要
安全性 低い 高い

enum class の宣言

enum class Rank { Gold = 1, Silver, Bronze };

その前に:型変換(暗黙的変換と明示的変換)

このあと enum classint に変換する場面が出てきます。先に「型変換」を整理しておきましょう。型変換には2種類あります。

暗黙的(あんもくてき)型変換 ― 自動で変換される

そのまま変換しても安全な型どうしは、コンパイラが自動で変換します。

int    n = 3;
double d = n;       // int → double に自動変換(d は 3.0)

double pi = 3.9;
int    m  = pi;     // double → int に自動変換(小数点以下は切り捨て、m は 3)

明示的(めいじてき)型変換 ― 自分で「変換する」と書く

「ここで変換する」とコードにはっきり書く方法です。C++では static_cast を使います。

double pi = 3.9;
int    m  = static_cast<int>(pi);   // 「int に変換する」と明示(m は 3)
static_cast の書き方:
static_cast<変換後の型>(変換したい値)
例:static_cast<int>(pi)double の値を int に変換します。
このあと出てくる enum class暗黙的変換が禁止されているため、int として扱いたいときは static_cast<int>(...)明示的に変換します。

enum class と switch文の組み合わせ

enum classswitch で使うには、2つの方法があります。

方法1:static_cast で int に変換して使う

#include <iostream>
using namespace std;

enum class Rank { Gold = 1, Silver, Bronze };

int main() {
    Rank rank = Rank::Silver;

    switch (static_cast<int>(rank)) {
        case 1:
            cout << "金賞" << endl;
            break;
        case 2:
            cout << "銀賞" << endl;
            break;
        case 3:
            cout << "銅賞" << endl;
            break;
        default:
            cout << "参加賞" << endl;
            break;
    }
    return 0;
}

方法2:enum class のまま使う(おすすめ)

switchenum class をそのまま渡し、case 側を Rank::Gold のようにスコープ付きで書く方法です。変換が要らず、こちらの方が読みやすくなります。

#include <iostream>
using namespace std;

enum class Rank { Gold = 1, Silver, Bronze };

int main() {
    Rank rank = Rank::Silver;

    switch (rank) {                 // 変換せず、そのまま渡せる
        case Rank::Gold:
            cout << "金賞" << endl;
            break;
        case Rank::Silver:
            cout << "銀賞" << endl;
            break;
        case Rank::Bronze:
            cout << "銅賞" << endl;
            break;
    }
    return 0;
}

コーディング演習

演習1:基本コードを動かす

06_01_switch.cpp を作成し、次のコードを入力して実行しましょう。
// switch_demo.cpp
#include <iostream>
using namespace std;

int main() {
    int day;
    cout << "曜日番号(1〜7)を入力:";
    cin >> day;

    switch (day) {
        case 1: cout << "日曜日" << endl; break;
        case 2: cout << "月曜日" << endl; break;
        case 3: cout << "火曜日" << endl; break;
        case 4: cout << "水曜日" << endl; break;
        case 5: cout << "木曜日" << endl; break;
        case 6: cout << "金曜日" << endl; break;
        case 7: cout << "土曜日" << endl; break;
        default: cout << "無効な番号です。" << endl; break;
    }
    return 0;
}

演習2:コードを改造する

06_01_switch.cpp をコピーして 06_02_switch_mod.cpp として保存し、次の変更を加えてみましょう:
ヒントを見る 本文の2つの方法のどちらでも書けます。
方法1:switch (static_cast<int>(day)) として case 1: … と整数で分ける。
方法2:switch (day) のまま case Day::Sat: … とスコープ付きで書く(変換不要で簡潔)。

理解度チェック

問題06-1

次のコードの出力はどれか。

#include <iostream>
using namespace std;
int main() {
    int rank = 2;
    switch (rank) {
        case 1: cout << "金賞" << endl; break;
        case 2: cout << "銀賞" << endl; break;
        case 3: cout << "銅賞" << endl; break;
        default: cout << "参加賞" << endl; break;
    }
    return 0;
}
解説を表示 正解:イ
rank == 2 により case 2 が実行され、「銀賞」と表示されます。break があるため case 3 以降は実行されません。

問題06-2

次のコードで break を取り除いた場合、rank = 1 のときの出力はどれか。

switch (rank) {
    case 1: cout << "金賞" << endl;
    case 2: cout << "銀賞" << endl;
    case 3: cout << "銅賞" << endl;
    default: cout << "参加賞" << endl;
}
解説を表示 正解:ウ
break がないため、case 1 にマッチした後もフォールスルーが起き、case 2、case 3、default まで全て実行されます。「金賞」「銀賞」「銅賞」「参加賞」が順番に表示されます。

問題06-3

enum class を使う主な利点として正しいものはどれか。

解説を表示 正解:イ
enum class の主な利点は名前のスコープが型内に閉じており、異なる enum 間での名前衝突を防げることです。通常の enum よりも型安全に使えます。

問題06-4

enum class Color { Red, Green, Blue }; と定義したとき、Color c = Color::Green;switch に渡すための正しい書き方はどれか。

解説を表示 正解:ア
enum class は暗黙の整数変換が禁止されているため、static_cast<int>(c) で明示的に int に変換する必要があります。Cスタイルキャスト(イ)も動作しますが、C++では static_cast の使用が推奨されます。

まとめ