この記事のポイント

  • アクセス修飾子の設計原則を体系整理
  • レビューで妥当性・責務境界をどう確認するか解説
  • 実務コード改善例・レビュー観点を提示

C++におけるアクセス修飾子の基本構造

| 修飾子 | 意味 | 使用領域 | |—|—|—|—| | public | 完全公開 | 外部API、利用者インターフェース | | protected | 継承者まで公開 | 継承設計時のみ利用 | | private | クラス内限定 | 内部状態・実装詳細 |

レビュー観点の本質

「責務の境界を誰にまで公開するのか?」


なぜレビュー対象になるのか

① カプセル化破壊を誘発しやすい

  • 過剰なpublic公開

② 継承設計不整合が生じやすい

  • protectedの安易乱用

③ 内部実装が外部依存に晒されやすい

  • メンバー変数のpublic化

④ 保守性が崩壊しやすい

  • 外部影響範囲の肥大化

アクセス修飾子レビュー原則

判定対象 設計判断
public 利用者が呼び出す必要がある最小範囲のみ
protected 継承戦略が明確なときのみ許可
private 原則デフォルト

良い実装例

class User {
public:
    User(int id, const std::string& name)
        : id_(id), name_(name) {}

    int id() const { return id_; }
    std::string name() const { return name_; }

private:
    int id_;
    std::string name_;
};

良い設計理由

  • 外部利用はgetter提供のみ
  • 内部状態は完全カプセル化
  • public範囲が明示的で読み取りやすい

レビュー観点

レビューアーは以下を確認する。

  • publicは利用者インターフェース最小限になっているか
  • protectedの乱用が無いか(継承責務の正当性確認)
  • privateがデフォルトで採用されているか
  • 実装詳細がpublic化されていないか
  • API利用者と実装保守者の責務境界が整理されているか

良くない実装例: ケース1

class User {
public:
    int id_;
    std::string name_;
};
@Reviewer
メンバー変数のpublic公開は禁止です。アクセサ提供に整理してください。

改善例

private:
    int id_;
    std::string name_;
public:
    int id() const;
    std::string name() const;

ケース2: protectedの安易な乱用

class Base {
protected:
    int internal_;
};
@Reviewer
継承戦略が曖昧ならprotected公開は避けてください。内部状態隠蔽が原則です。

改善例

private:
    int internal_;
public:
    void setInternal(int val);
    int getInternal() const;

ケース3: 実装詳細のAPI化

class Cache {
public:
    std::unordered_map<std::string, std::string> data_;
};
@Reviewer
内部実装型をpublic化せず専用API提供に整理してください。

改善例

private:
    std::unordered_map<std::string, std::string> data_;
public:
    void put(const std::string& key, const std::string& value);
    std::string get(const std::string& key) const;

ケース4: 継承前提の不安定protected

class Shape {
protected:
    int id_;
};
@Reviewer
継承利用方針を明確に設計説明できる時のみprotectedを許可します。

改善例

class Shape {
private:
    int id_;
protected:
    Shape(int id);  // 初期化専用責務に限定
};

ケース5: getter/setterの無思考大量公開

class Config {
public:
    int getA() const;
    void setA(int);
    int getB() const;
    void setB(int);
    int getC() const;
    void setC(int);
};
@Reviewer
設定責務全体でまとめたAPI設計整理を優先検討してください。

改善例

class Config {
public:
    void applySettings(const Settings&);
};

ケース6: モジュール間friend代替public

class Core {
public:
    friend class ModuleA;
    friend class ModuleB;
};
@Reviewer
friend代替でpublic化する設計はカプセル化破壊です。責務再整理してください。

改善例

Coreは必要最小限APIだけをpublic公開

アクセス修飾子レビューの実務意義

防止崩壊 設計効果
カプセル化崩壊 実装詳細封鎖
保守不能化 API境界安定化
継承爆発 責務整理
外部依存肥大 影響範囲制御

観点チェックリスト


まとめ

レビューアーが自問すべき本質はこれです:

「本当に外部からこの責務が見えて良いのか?」

  • public公開はAPI設計の約束
  • protected公開は設計責任を要説明

「カプセル化境界レビュー」こそC++設計育成の基本技法です。