コンテンツにスキップ

C++/アクセス指定子

出典: フリー教科書『ウィキブックス(Wikibooks)』
< C++

アクセス指定子の基礎

[編集]

概要

[編集]

アクセス指定子は、C++におけるカプセル化と情報隠蔽の主要なメカニズムです。クラスや構造体のメンバー(変数・関数)へのアクセス制御を設定し、以下の目的を達成します:

  • データの保護とカプセル化の実現
  • クラスインターフェースの明確な定義
  • 継承階層における適切なアクセス制御

基本的な指定子

[編集]

C++は3種類の基本的なアクセス指定子を提供します:

public
* クラス外部から自由にアクセス可能
* インターフェースの公開に使用
* 例:クラスのAPIとして公開するメソッド
private
* クラス内部からのみアクセス可能
* データ隠蔽の実現に使用
* 例:内部実装の詳細、状態管理変数
protected
* クラス内部と派生クラスからアクセス可能
* 継承を考慮した設計に使用
* 例:派生クラスでオーバーライドされるメソッド

構文と使用法

[編集]
class Example {
public:
    void publicMethod();    // 外部からアクセス可能
private:
    int privateData;        // クラス内部のみ
protected:
    virtual void protectedMethod();  // 派生クラスも可
};

モダンC++におけるアクセス制御

[編集]

C++17以降の新機能

[編集]

インライン変数とstatic constexpr

[編集]
class Modern {
public:
    static inline int counter = 0;  // C++17: クラス内インライン変数
    static constexpr int MAX = 100; // コンパイル時定数
private:
    inline static int internal = 0; // private なインライン変数
};

構造化束縛とアクセス制御

[編集]
class DataHolder {
public:
    auto getData() const {
        return std::tuple{value1, value2};
    }
private:
    int value1 = 0;
    int value2 = 0;
};

// 使用例
auto [v1, v2] = dataHolder.getData();

C++20の拡張

[編集]

コンセプトとアクセス制御

[編集]
template<typename T>
concept Accessible = requires(T t) {
    { t.publicMethod() } -> std::same_as<void>;
};

class Modern {
public:
    void publicMethod() requires Accessible<Modern>;
private:
    void privateMethod();
};

モジュールでのアクセス制御

[編集]
// mymodule.cpp
export module mymodule;

export class Public {
    // モジュール外部から見える
};

class Private {
    // モジュール内部でのみ見える
};

アクセス制御のベストプラクティス

[編集]

設計原則

[編集]
  1. デフォルトでprivate
    • メンバーは特に理由がない限りprivateにする
    • 必要に応じて段階的に公開レベルを上げる
  2. インターフェースの最小化
    • publicメンバーは必要最小限に抑える
    • 実装の詳細は完全に隠蔽する
  3. 継承を考慮した設計
    • protectedは慎重に使用する
    • 派生クラスに必要な機能のみを公開

パターンと実践例

[編集]

PIMPLイディオム

[編集]
PIMPLイディオム(Pointer to Implementation)は、クラスの実装をヘッダーファイルから分離し、プライベートな実装をポインタを通じて管理することで、コンパイル時間の短縮や依存関係の削減を実現する設計パターンです。
// ヘッダーファイル
class Widget {
public:
    Widget();
    ~Widget();
    void doSomething();
private:
    class Impl;
    std::unique_ptr<Impl> pimpl;
};

// 実装ファイル
class Widget::Impl {
    // 実装の詳細
};

インターフェースクラス

[編集]
class IShape {
public:
    virtual ~IShape() = default;
    virtual double area() const = 0;
protected:
    // 派生クラスで使用する共通機能
    virtual void transform() = 0;
private:
    // 実装の詳細
};

アクセス制御の応用

[編集]

フレンド宣言

[編集]

クラス間の特別なアクセス権を付与します:

class Secretary {
    friend class Manager;  // Managerクラスに特別なアクセス権を付与
private:
    void accessConfidentialData();
};

テンプレートとアクセス制御

[編集]
template<typename T>
class Container {
public:
    void add(const T& item);
private:
    std::vector<T> items;
    using Iterator = typename std::vector<T>::iterator;
protected:
    virtual void onItemAdded(const T& item);
};

高度なトピック

[編集]

アクセス指定子の継承制御

[編集]

継承時のアクセス指定子による影響:

基底クラスのメンバー public継承 protected継承 private継承
public public protected private
protected protected protected private
private アクセス不可 アクセス不可 アクセス不可

スマートポインタとアクセス制御

[編集]
class Resource {
public:
    static std::shared_ptr<Resource> create() {
        return std::shared_ptr<Resource>(new Resource());
    }
private:
    Resource() = default;  // 直接のインスタンス化を防ぐ
};

まとめ

[編集]

アクセス指定子は、C++のカプセル化とデータ隠蔽の中心的なメカニズムです。モダンC++では、より洗練された使用方法と新しい機能が追加され、より柔軟で安全なコード設計が可能になっています。適切なアクセス制御の実装は、保守性が高く、拡張しやすいコードの作成に不可欠です。