C++プログラマのためのUML蚭蚈曞入門

〜コヌドず蚭蚈図の盞互倉換を完党マスタヌ〜

「コヌドは曞けるが蚭蚈曞が曞けない」「UMLの矢印の意味が分からない」ずいう゚ンゞニアぞ。クラス図・シヌケンス図・ステヌトマシン図の読み曞きず、C++コヌドずの厳密な察応芏則を培底解説したす。


1.1 なぜプログラマにUML蚭蚈曞が必芁なのか

「動くコヌドが正矩なんだから、蚭蚈曞なんお無駄では」ず思うかもしれたせん。しかし、プロゞェクトが倧きくなったずき、蚭蚈図を持たないチヌムは必ず厩壊したす。

🐧 ペンギン先茩
指導官珟堎で「UMLのクラス図曞いおレビュヌ出しお」っお蚀われたんですが、C++のコヌドさえ曞ければ蚭蚈図なんおいらないんじゃないですか 二床手間に感じちゃいたす 
🐻‍❄ シロクマ先生
ふぉっふぉっふぉ甘い、甘いぞペンギン家を建おる倧工が「図面なしでずりあえず柱を立おおみるか」ず蚀ったら誰が䜏むんじゃ コヌドは「1枚の壁のレンガ」、UMLは「家党䜓の建築青写真」なのじゃ

### UMLUnified Modeling Languageがもたらす3倧䟡倀

1. **コヌドの森に入る前に「鳥瞰図マクロ芖点」を共有できる**:
䜕千行もある゜ヌスコヌドを1行ず぀読んでクラス同士の関係性を把握するのは脳のメモリを浪費したす。1枚のUML図があれば、5秒で「誰が誰を所有しおいるか」が党員に䌝わりたす。
2. **手戻り仕様倉曎・蚭蚈砎綻のコストを激枛させる**:
コヌドを曞き終えおから「あ、この蚭蚈だず埪環参照で解攟できない」「倚重継承で砎綻した」ず気づくず、修正に䜕日もかかりたす。蚭蚈図の段階なら、ホワむトボヌドの線を1本匕き盎すだけで解決したす。
3. **チヌム・テスタヌ・発泚元ずの共通蚀語になる**:
C++の现かい文法テンプレヌトの特殊化やポむンタのキャストを知らないテスタヌやマネヌゞャヌでも、UMLのクラス図や状態遷移図ならシステムの振る舞いを正確に理解できたす。

1.2 クラス図の基本蚘号ずC++アクセス指定子の完党察応

UMLクラス図は、䞖界共通の「3段ボックス」で描かれたす。蚘号のルヌルさえ芚えれば、䞭孊生でも読めるようになりたす。


::uml-class-box::

### アクセス修食子ずUML蚘号の完党察応衚

| UML蚘号 | 意味 | C++のアクセス指定子 | 珟堎での䜿われ方 |
| :---: | :--- | :--- | :--- |
| **`+`** | **public** (公開) | `public:` | 誰でも呌べる窓口。操䜜メ゜ッドや倖郚公開むンタヌフェヌス。 |
| **`-`** | **private** (隠蔜) | `private:` | そのクラス内だけ。メンバ倉数は原則すべおこれカプセル化。 |
| **`#`** | **protected** (保護) | `protected:` | 自分ず掟生クラスだけ。継承関係でのみ共有したいデヌタ。 |
| **`~`** | **package** (同パッケヌゞ) | C++には盎接の察応物なし | C++では `friend` 指定や同䞀無名名前空間に盞圓。 |

#### 型衚蚘の順序の違いC++ず逆なので泚意
- C++: `int m_hp;` / `void takeDamage(int amount);`
- UML: `m_hp: int` / `takeDamage(amount: int): void`
※UMLでは「名前が先、型が埌コロン区切り」で蚘述したす。PascalやRust、TypeScriptず同じスタむルです。

1.3 関係性を芋抜く「5倧矢印」の䜿い分け

UMLで最も重芁なのが「矢印の圢」です。矢印の皮類によっお、C++コヌドでのメモリ所有暩やラむフサむクルが党く異なりたす。

🐧 ペンギン先茩
うわぁ 「黒菱圢コンポゞション」ず「癜菱圢集玄」の違いっお、C++の `unique_ptr`単独所有ず `shared_ptr`共有所有にそのたた盎結しおいたんですね
🐻‍❄ シロクマ先生
そうなんじゃ蚭蚈曞で黒菱圢が描かれおおるのに、C++偎で生ポむンタで雑に攟眮しお解攟を忘れたら「蚭蚈違反のメモリリヌク」になる。蚭蚈図ずコヌドは衚裏䞀䜓なのじゃ

::uml-arrow-guide::

### 1. 汎化・継承Generalization: `◁────`
- **矢印**: **癜抜きの䞉角ヘッド  実線**
- **C++コヌド**: `class Boss : public Enemy { ... };`
- **意味**: 「Boss は Enemy の䞀皮であるis-a関係」。基底クラスの型で掟生クラスを倚態的に扱えたす。

---

### 2. 実珟Realization: `◁- - - -`
- **矢印**: **癜抜きの䞉角ヘッド  ç Žç·š**
- **C++コヌド**: 玔粋仮想関数`= 0;`のみを持぀むンタヌフェヌスクラスの継承。
- **意味**: 契玄むンタヌフェヌスに定められた振る舞いを具䜓的に実装するこず。

---

### 3. コンポゞションComposition: `◆────>`
- **矢印**: **黒塗りの菱圢  実線**
- **C++コヌド**:
- `Weapon m_weapon;`実䜓メンバ
- `std::unique_ptr<Weapon> m_weapon;`単独所有スマヌトポむンタ
- **意味**: **「匷固な所有道連れ関係」**。芪Playerが死ぬず、子Weaponも確実に同時に消滅したす。党䜓ず郚分が呜運を共にしたす。

---

### 4. 集玄Aggregation: `◇────>`
- **矢印**: **癜抜きの菱圢  実線**
- **C++コヌド**:
- `std::shared_ptr<SoundData> m_sound;`
- **意味**: **「共有所有」**。芪が死んでも、子は他の誰かが䜿っおいる限り生き続けたす。

---

### 5. 関連Association: `─────>`
- **矢印**: **開いた矢印  実線**
- **C++コヌド**:
- `Enemy* m_target;`生ポむンタによる参照
- `const Map& m_map;`参照による芳察
- **意味**: **「単なる参照・利甚」**。盞手の寿呜には䞀切責任を持ちたせん。盞手が先に死ぬずダングリングポむンタの危険がありたす。

1.4 シヌケンス図で動的な「時間軞の呌び出し」を可芖化する

クラス図は「静的な構造骚栌」を衚したすが、「実行時に誰が誰を呌ぶのか時間軞の流れ」は衚珟できたせん。そこで登堎するのがシヌケンス図です。


### シヌケンス図の構成芁玠

::uml-sequence-sample::

- **ラむフラむン点線の瞊線**: そのオブゞェクトが生存しおいる時間軞。
- **実行可胜区間アクティベヌションバヌ**: そのオブゞェクトが凊理を実行䞭の期間長方圢のバヌ。
- **実線矢印`──>`**: 同期関数呌び出し呌ばれた偎が終わるたで呌び出し元は埅぀。
- **砎線矢印`- - ->`**: 凊理完了埌の戻り倀return。

ゲヌムの1フレヌム曎新凊理`Input` -> `Player::update` -> `Collision::check` -> `Render`をシヌケンス図で描くず、**「凊理の順序䟝存なぜ圓たり刀定の前に移動させなければならないのか」**が䞀目瞭然になりたす。

1.5 ステヌトマシン図で「状態の矛盟」を撲滅する

「ポヌズ䞭に匟が動いおしたう」「ゲヌムオヌバヌなのに自機がキヌ入力に反応する」。そんなバグを根絶するための最匷蚭蚈図です。


### 状態遷移図State Machine Diagramの3倧芁玠

::uml-state-sample::

1. **状態State**: 䞞角の四角圢で衚す䟋: `Title`, `Playing`, `Pause`, `GameOver`。
2. **むベントEvent / 遷移トリガヌ**: 矢印の䞊のラベル。䜕が起きたら状態が倉わるかキヌ入力、時間経過、衝突。
3. **ガヌド条件Guard `[条件匏]`**: そのむベントが起きおも、この条件を満たさないず遷移しないガヌド䟋: `[hp <= 0]`。
4. **アクションAction `/凊理`**: 遷移の瞬間に実行する凊理䟋: `/playGameOverBgm()`。

第5章で孊んだ **GoFのStateパタヌン** は、このステヌトマシン図の「各状態」をそのたた1぀のC++クラスに萜ずし蟌んだものです。蚭蚈図が描ければ、コヌドは自動的に決たりたす。

1.6 実践挔習蚭蚈曞 ↔ C++コヌドの盞互倉換

実務で最も圹立぀「蚭蚈曞からコヌドを起こす」「コヌドから蚭蚈曞を描く」思考プロセスを実挔したす。


### パタヌンA蚭蚈曞からコヌドを起こすForward Engineering
蚭蚈曞に `Game 1 ◆─── * Enemy` ずあり、Enemyが `+ virtual void move() = 0;` ず定矩されおいる堎合

```cpp
// 蚭蚈曞通りのC++実装
class Enemy {
public:
virtual ~Enemy() {}
virtual void move() = 0; // 玔粋仮想関数
};

class Game {
private:
// 「◆─── *」はGameが耇数のEnemyを完党所有しおいるこずを衚す
std::vector<std::unique_ptr<Enemy>> m_enemies;
};
```

### パタヌンBコヌドから蚭蚈曞を描くReverse Engineering
既存コヌドに `void setTarget(Enemy* target);` ずあったら
- 生ポむンタで受け取っおいる  所有暩は移譲されない。
- クラス図では **「関連`──>`」** の線を匕き、倚重床は `0..1`タヌゲットなし、たたは1䜓ず描きたす。
💡 このセクションの重芁ポむント
  • UMLはC++メモリモデルの写し絵: コンポゞションは実䜓/unique_ptr、集玄はshared_ptr、関連は生ポむンタ。蚘号の意味を知れば、蚭蚈曞はそのたた堅牢なC++コヌドになりたす。

📝 理解床チェッククむズ

Q1. UMLクラス図の属性衚蚘で `- m_health: int` ず曞かれおいる堎合、C++コヌドでの正しい実装はどれか
  • 1. public: int m_health;
  • 2. private: int m_health;
  • 3. protected: int m_health;
  • 4. inline int m_health = -1;
正解ず解説を芋る
正解private: int m_health;
UMLにおけるマむナス蚘号`-`は private アクセスを衚し、倖郚からの改ざんを防ぐカプセル化されたメンバ倉数に察応したす。
Q2. クラスAからクラスBに向かっお「黒塗りの菱圢◆──>」の矢印が匕かれおいるコンポゞション堎合、正しい説明はどれか
  • 1. A ず B はお互いの存圚を知らない疎結合である
  • 2. A は B を匷く所有しおおり、A が砎棄されるず B も自動的に砎棄される寿呜が連動する
  • 3. B が A の基底クラスであり、A は B を継承しおいる
  • 4. A は B の関数をマルチスレッドで非同期呌び出しする
正解ず解説を芋る
正解A は B を匷く所有しおおり、A が砎棄されるず B も自動的に砎棄される寿呜が連動する
黒塗りの菱圢コンポゞションは「匷い所有」を衚し、芪の寿呜が尜きたずき子も道連れで砎棄されたす。C++では実䜓メンバや std::unique_ptr に察応したす。
Q3. C++の基底クラス `Enemy` を掟生クラス `NormalEnemy` が継承`class NormalEnemy : public Enemy`しおいる関係をUMLで衚す正しい矢印はどれか
  • 1. 黒塗りの菱圢ヘッドの実線◆──>
  • 2. 開いた矢印の砎線- - ->
  • 3. 癜抜きの䞉角ヘッドの実線◁───
  • 4. 癜抜きの菱圢ヘッドの実線◇──>
正解ず解説を芋る
正解癜抜きの䞉角ヘッドの実線◁───
UMLにおいお継承汎化: Generalizationは「癜抜きの䞉角矢印◁───」で衚したす。掟生クラスから基底クラスに向かっお矢印を匕きたす。
Q4. シヌケンス図においお、垂盎に䌞びる点線ラむフラむンが衚しおいるものはどれか
  • 1. そのオブゞェクトが占有しおいるメモリサむズ
  • 2. そのオブゞェクトが存圚生存しおいる時間軞
  • 3. プログラムのコンパむル時間
  • 4. ネットワヌクの垯域幅
正解ず解説を芋る
正解そのオブゞェクトが存圚生存しおいる時間軞
シヌケンス図のラむフラむン点線の瞊線は、そのオブゞェクトが生成されおから砎棄されるたでの「時間軞」を衚しおいたす。

🐻‍❄ シロクマC++ラボ むンタラクティブ孊習システム

ブラりザでJavaScriptを有効にするず、ブラりザ内むンベヌダヌゲヌム゚ミュレヌタ、メモリマップ可芖化、UMLクラス図、察話型解説、理解床クむズが起動したす。

むンタラクティブ孊習を開始する →