【C++】enumとenum classの違いとは?|状態を安全に管理する書き方

C++

今回は、C++でよく出てくる「enumとenum classの違い」について解説していきます。

「enumって何?」
「enum classとふつうのenum、何が違うの?」
「ゲームの状態管理に使うと聞くけど、どう書くの?」

こんな疑問はありませんか?

キャラクターの状態(待機・歩行・ジャンプ)のように、決まった種類を扱う場面はゲームでとても多いです。そこで 0, 1, 2 のような数字を直接使うと分かりにくくなりますが、enumを使うと意味のある名前で書けるようになります。

この記事を読み終えると、あなたはenumの意味・enum classとの違い・ゲームでの状態管理・初心者がハマりやすいミスをしっかり理解できると思いますので、ぜひ最後まで読んでいただけると嬉しいです。

enumとは?

enum(列挙型)とは、関連する定数に名前を付けてまとめたものです。「状態」や「モード」など、種類が決まっているものを表すのに向いています。

#include <iostream>

// 昔ながらの enum
enum State {
    Idle,  // 0
    Walk,  // 1
    Jump   // 2
};

int main() {
    State s = Walk;
    std::cout << "状態番号: " << s << "n"; // 1
    return 0;
}
状態番号: 1

0, 1, 2 のようなマジックナンバーを、IdleWalk という名前で書けるので一気に読みやすくなります。

従来のenumの問題点

便利な従来のenumですが、2つの弱点があります。

  • 名前がグローバルに漏れる → 別のenumと名前が衝突しやすい
  • int勝手に変換される → 意図しない比較が通ってしまう

たとえば別の enum にも Idle があると、それだけでコンパイルエラーになってしまいます。

enum class(スコープ付きenum)

そこで登場するのが enum class です。名前が衝突せず、intへ勝手に変換されない、安全なenumです。使うときは State::Idle のように「型名::」を付けます。

#include <iostream>

enum class State {
    Idle,
    Walk,
    Jump
};

int main() {
    State s = State::Jump;

    if (s == State::Jump) {
        std::cout << "ジャンプ中!n";
    }
    return 0;
}
ジャンプ中!

今どきのC++では、基本的に enum class を使えばOKです。安全でバグりにくいのが理由です。

実践例:ゲームの状態管理

enum classは、キャラの状態を switch で切り替えるときにとても読みやすくなります。

void Update(State s) {
    switch (s) {
    case State::Idle: /* 待機の処理 */ break;
    case State::Walk: /* 歩行の処理 */ break;
    case State::Jump: /* ジャンプの処理 */ break;
    }
}

状態をもっと本格的に管理したい場合は、ステートパターンの記事もあわせて読むと設計の幅が広がります。switch の使い方はswitch文が使えないケースの記事も参考になります。

【重要】私が実際にenumで困った体験談

個人開発で、キャラの状態 enum と、シーンの状態 enum の両方に Idle を作ってしまい、ある日いきなり「識別子が再定義されています」というコンパイルエラーが大量に出て焦りました。

原因は、昔ながらの enum が名前をグローバルにばらまいていたこと。両方を enum class に変えたら、CharaState::IdleSceneState::Idle で区別されて一発で解決しました。それ以来、enumは enum class で書くようにしています。

enum使用時のよくある失敗例と対処法

①enum classをそのまま数値として使う

enum classは int に自動変換されません。数値が必要なときは static_cast<int>(s) と明示的に変換します。

②「型名::」を付け忘れる

enum classでは Idle ではなく State::Idle と書く必要があります。付け忘れるとエラーになります。

③switchで全ケースを処理し忘れる

状態を追加したのに switchcase を足し忘れると、その状態だけ何も起きません。状態を増やしたら switch も見直すクセをつけましょう。

注意点

  • 今どきのC++では基本 enum class を使う
  • 数値化したいときは static_cast で明示的に変換する
  • 状態を増やしたら、対応する switch も忘れず更新する

まとめ

  • enumは関連する定数に名前を付けてまとめる仕組み
  • 従来のenumは名前衝突・int変換の弱点がある
  • enum class は安全で衝突しない。基本こちらを使う
  • ゲームの状態管理と switch の相性が抜群

enum classは、状態やモードを安全に管理するための強い味方です。まずはキャラの状態管理あたりから enum class で書いてみてください。

関連記事