[C++] クラス変数でアクセスできるメンバとできないメンバとは?

C++において、クラス変数(インスタンス変数)からアクセスできるメンバは、主にそのクラスの「アクセス修飾子」によって制御されます。

publicメンバはクラス外部からもアクセス可能で、privateメンバはクラス内部からのみアクセス可能です。

protectedメンバは、クラス自身および派生クラスからアクセスできます。

クラス変数を通じてアクセスできるのは、publicメンバと、クラス内部のメソッドからアクセスされるprivateおよびprotectedメンバです。

この記事でわかること
  • C++のアクセス修飾子の役割
  • public、private、protectedの違い
  • 静的メンバの特性と使い方
  • コンストラクタとデストラクタのアクセス
  • アクセス修飾子を活用した設計例

目次から探す

クラスメンバの種類とアクセス修飾子

クラスメンバとは?

クラスメンバは、クラス内で定義される変数や関数のことを指します。

これらは、クラスのインスタンス(オブジェクト)が持つ属性や動作を表現します。

クラスメンバは、オブジェクトの状態を管理したり、特定の機能を実装したりするために使用されます。

クラスメンバには、インスタンスメンバと静的メンバの2種類があります。

アクセス修飾子の役割

アクセス修飾子は、クラスメンバへのアクセス制御を行うためのキーワードです。

これにより、クラス外部からのアクセスを制限したり、特定のクラスや関数からのみアクセスできるようにしたりします。

C++では、主に以下の3つのアクセス修飾子が使用されます。

スクロールできます
修飾子説明
publicクラス外部からもアクセス可能
privateクラス内部からのみアクセス可能
protectedクラス内部および派生クラスからアクセス可能

public、private、protectedの違い

  • public: この修飾子が付けられたメンバは、クラスの外部からもアクセスできます。

一般的に、外部に公開したいメンバに使用します。

  • private: この修飾子が付けられたメンバは、クラスの内部からのみアクセス可能です。

外部からのアクセスを制限することで、データの隠蔽を実現します。

  • protected: この修飾子が付けられたメンバは、クラスの内部およびその派生クラスからアクセス可能です。

継承を利用したクラス設計において、特定のメンバを派生クラスに公開したい場合に使用します。

クラス変数とクラスメソッドの違い

  • クラス変数: クラスに属する変数で、全てのインスタンスで共有されます。

static修飾子を使って定義されます。

  • クラスメソッド: クラスに属する関数で、クラス変数や他のクラスメンバにアクセスするために使用されます。

クラスメソッドもstatic修飾子を使って定義されることがあります。

以下は、クラス変数とクラスメソッドの例です。

#include <iostream>
using namespace std;
class Example {
public:
    static int classVariable; // クラス変数
    static void classMethod() { // クラスメソッド
        cout << "クラスメソッドが呼ばれました。" << endl;
    }
};
int Example::classVariable = 0; // クラス変数の初期化
int main() {
    Example::classMethod(); // クラスメソッドの呼び出し
    return 0;
}
クラスメソッドが呼ばれました。

静的メンバ(static)の扱い

静的メンバは、クラスに属するメンバであり、全てのインスタンスで共有されます。

静的メンバは、クラスがインスタンス化される前にメモリに割り当てられ、クラスの全インスタンスで同じ値を持ちます。

静的メンバは、static修飾子を使って定義され、クラス名を通じてアクセスされます。

以下は、静的メンバの例です。

#include <iostream>
using namespace std;
class Counter {
public:
    static int count; // 静的メンバ
    Counter() {
        count++; // コンストラクタでカウントを増やす
    }
};
int Counter::count = 0; // 静的メンバの初期化
int main() {
    Counter obj1; // インスタンス生成
    Counter obj2; // インスタンス生成
    cout << "現在のカウント: " << Counter::count << endl; // 静的メンバへのアクセス
    return 0;
}
現在のカウント: 2

publicメンバへのアクセス

publicメンバの定義方法

publicメンバは、クラス内でpublicキーワードを使用して定義されます。

これにより、クラスの外部からもアクセス可能なメンバを作成できます。

以下は、publicメンバの定義方法の例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    int publicVariable; // publicメンバ変数
    void publicMethod() { // publicメンバ関数
        cout << "これはpublicメソッドです。" << endl;
    }
};
int main() {
    MyClass obj; // クラスのインスタンス生成
    obj.publicVariable = 10; // publicメンバ変数へのアクセス
    obj.publicMethod(); // publicメンバ関数の呼び出し
    return 0;
}
これはpublicメソッドです。

クラス外部からのアクセス

publicメンバは、クラスの外部から直接アクセスすることができます。

インスタンスを通じて、publicメンバにアクセスすることが可能です。

以下は、クラス外部からのアクセスの例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    int publicVariable; // publicメンバ変数
};
int main() {
    MyClass obj; // クラスのインスタンス生成
    obj.publicVariable = 20; // publicメンバ変数へのアクセス
    cout << "publicVariableの値: " << obj.publicVariable << endl; // 値の表示
    return 0;
}
publicVariableの値: 20

クラス内部からのアクセス

クラス内部からもpublicメンバにアクセスすることができます。

クラスのメンバ関数から、同じクラス内のpublicメンバにアクセスすることが可能です。

以下は、クラス内部からのアクセスの例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    int publicVariable; // publicメンバ変数
    void setVariable(int value) { // publicメンバ関数
        publicVariable = value; // publicメンバ変数へのアクセス
    }
    void displayVariable() { // publicメンバ関数
        cout << "publicVariableの値: " << publicVariable << endl; // 値の表示
    }
};
int main() {
    MyClass obj; // クラスのインスタンス生成
    obj.setVariable(30); // publicメンバ関数の呼び出し
    obj.displayVariable(); // publicメンバ関数の呼び出し
    return 0;
}
publicVariableの値: 30

継承時のpublicメンバの扱い

継承を使用する場合、publicメンバは派生クラスからもアクセス可能です。

基底クラスのpublicメンバは、派生クラスのインスタンスを通じて直接アクセスできます。

以下は、継承時のpublicメンバの扱いの例です。

#include <iostream>
using namespace std;
class BaseClass {
public:
    int publicVariable; // publicメンバ変数
};
class DerivedClass : public BaseClass { // BaseClassを継承
public:
    void displayVariable() { // publicメンバ関数
        cout << "publicVariableの値: " << publicVariable << endl; // 基底クラスのpublicメンバへのアクセス
    }
};
int main() {
    DerivedClass obj; // 派生クラスのインスタンス生成
    obj.publicVariable = 40; // 基底クラスのpublicメンバへのアクセス
    obj.displayVariable(); // 派生クラスのpublicメンバ関数の呼び出し
    return 0;
}
publicVariableの値: 40

privateメンバへのアクセス

privateメンバの定義方法

privateメンバは、クラス内でprivateキーワードを使用して定義されます。

この修飾子を使用することで、クラスの外部からのアクセスを制限し、データの隠蔽を実現します。

以下は、privateメンバの定義方法の例です。

#include <iostream>
using namespace std;
class MyClass {
private:
    int privateVariable; // privateメンバ変数
public:
    void setVariable(int value) { // publicメンバ関数
        privateVariable = value; // privateメンバ変数へのアクセス
    }
    void displayVariable() { // publicメンバ関数
        cout << "privateVariableの値: " << privateVariable << endl; // 値の表示
    }
};
int main() {
    MyClass obj; // クラスのインスタンス生成
    obj.setVariable(50); // publicメンバ関数の呼び出し
    obj.displayVariable(); // publicメンバ関数の呼び出し
    return 0;
}
privateVariableの値: 50

クラス外部からのアクセス制限

privateメンバは、クラスの外部から直接アクセスすることができません。

外部からprivateメンバにアクセスしようとすると、コンパイルエラーが発生します。

以下は、クラス外部からのアクセス制限の例です。

#include <iostream>
using namespace std;
class MyClass {
private:
    int privateVariable; // privateメンバ変数
public:
    void setVariable(int value) { // publicメンバ関数
        privateVariable = value; // privateメンバ変数へのアクセス
    }
};
int main() {
    MyClass obj; // クラスのインスタンス生成
    // obj.privateVariable = 60; // エラー: privateメンバへのアクセス
    obj.setVariable(60); // publicメンバ関数の呼び出し
    return 0;
}
(コンパイルエラー)

クラス内部からのアクセス

クラス内部からは、privateメンバにアクセスすることができます。

クラスのメンバ関数から、同じクラス内のprivateメンバにアクセスすることが可能です。

以下は、クラス内部からのアクセスの例です。

#include <iostream>
using namespace std;
class MyClass {
private:
    int privateVariable; // privateメンバ変数
public:
    void setVariable(int value) { // publicメンバ関数
        privateVariable = value; // privateメンバ変数へのアクセス
    }
    void displayVariable() { // publicメンバ関数
        cout << "privateVariableの値: " << privateVariable << endl; // 値の表示
    }
};
int main() {
    MyClass obj; // クラスのインスタンス生成
    obj.setVariable(70); // publicメンバ関数の呼び出し
    obj.displayVariable(); // publicメンバ関数の呼び出し
    return 0;
}
privateVariableの値: 70

フレンド関数(friend)によるアクセス

フレンド関数を使用することで、privateメンバにアクセスすることができます。

フレンド関数は、特定のクラスのprivateメンバにアクセスする権限を持つ関数です。

以下は、フレンド関数によるアクセスの例です。

#include <iostream>
using namespace std;
class MyClass {
private:
    int privateVariable; // privateメンバ変数
public:
    MyClass(int value) : privateVariable(value) {} // コンストラクタ
    friend void displayPrivateVariable(MyClass& obj); // フレンド関数の宣言
};
void displayPrivateVariable(MyClass& obj) { // フレンド関数
    cout << "privateVariableの値: " << obj.privateVariable << endl; // privateメンバへのアクセス
}
int main() {
    MyClass obj(80); // クラスのインスタンス生成
    displayPrivateVariable(obj); // フレンド関数の呼び出し
    return 0;
}
privateVariableの値: 80

継承時のprivateメンバの扱い

継承を使用する場合、privateメンバは派生クラスから直接アクセスすることができません。

基底クラスのprivateメンバは、派生クラスからは見えないため、アクセスするには基底クラスのpublicまたはprotectedメンバを介する必要があります。

以下は、継承時のprivateメンバの扱いの例です。

#include <iostream>
using namespace std;
class BaseClass {
private:
    int privateVariable; // privateメンバ変数
public:
    BaseClass(int value) : privateVariable(value) {} // コンストラクタ
    int getPrivateVariable() { // publicメンバ関数
        return privateVariable; // privateメンバへのアクセス
    }
};
class DerivedClass : public BaseClass { // BaseClassを継承
public:
    DerivedClass(int value) : BaseClass(value) {} // コンストラクタ
};
int main() {
    DerivedClass obj(90); // 派生クラスのインスタンス生成
    cout << "privateVariableの値: " << obj.getPrivateVariable() << endl; // 基底クラスのpublicメンバ関数の呼び出し
    return 0;
}
privateVariableの値: 90

protectedメンバへのアクセス

protectedメンバの定義方法

protectedメンバは、クラス内でprotectedキーワードを使用して定義されます。

この修飾子を使用することで、クラスの外部からのアクセスを制限しつつ、派生クラスからはアクセス可能にすることができます。

以下は、protectedメンバの定義方法の例です。

#include <iostream>
using namespace std;
class MyClass {
protected:
    int protectedVariable; // protectedメンバ変数
public:
    MyClass(int value) : protectedVariable(value) {} // コンストラクタ
};
int main() {
    MyClass obj(100); // クラスのインスタンス生成
    // obj.protectedVariable = 200; // エラー: protectedメンバへのアクセス
    return 0;
}
(コンパイルエラー)

クラス外部からのアクセス制限

protectedメンバは、クラスの外部から直接アクセスすることができません。

外部からprotectedメンバにアクセスしようとすると、コンパイルエラーが発生します。

以下は、クラス外部からのアクセス制限の例です。

#include <iostream>
using namespace std;
class MyClass {
protected:
    int protectedVariable; // protectedメンバ変数
public:
    MyClass(int value) : protectedVariable(value) {} // コンストラクタ
};
int main() {
    MyClass obj(150); // クラスのインスタンス生成
    // obj.protectedVariable = 250; // エラー: protectedメンバへのアクセス
    return 0;
}
(コンパイルエラー)

クラス内部からのアクセス

クラス内部からは、protectedメンバにアクセスすることができます。

クラスのメンバ関数から、同じクラス内のprotectedメンバにアクセスすることが可能です。

以下は、クラス内部からのアクセスの例です。

#include <iostream>
using namespace std;
class MyClass {
protected:
    int protectedVariable; // protectedメンバ変数
public:
    MyClass(int value) : protectedVariable(value) {} // コンストラクタ
    void displayVariable() { // publicメンバ関数
        cout << "protectedVariableの値: " << protectedVariable << endl; // 値の表示
    }
};
int main() {
    MyClass obj(200); // クラスのインスタンス生成
    obj.displayVariable(); // publicメンバ関数の呼び出し
    return 0;
}
protectedVariableの値: 200

継承時のprotectedメンバの扱い

継承を使用する場合、protectedメンバは派生クラスからアクセス可能です。

基底クラスのprotectedメンバは、派生クラスのインスタンスを通じて直接アクセスできます。

以下は、継承時のprotectedメンバの扱いの例です。

#include <iostream>
using namespace std;
class BaseClass {
protected:
    int protectedVariable; // protectedメンバ変数
public:
    BaseClass(int value) : protectedVariable(value) {} // コンストラクタ
};
class DerivedClass : public BaseClass { // BaseClassを継承
public:
    DerivedClass(int value) : BaseClass(value) {} // コンストラクタ
    void displayVariable() { // publicメンバ関数
        cout << "protectedVariableの値: " << protectedVariable << endl; // 基底クラスのprotectedメンバへのアクセス
    }
};
int main() {
    DerivedClass obj(300); // 派生クラスのインスタンス生成
    obj.displayVariable(); // 派生クラスのpublicメンバ関数の呼び出し
    return 0;
}
protectedVariableの値: 300

protectedとprivateの違い

  • アクセス範囲: privateメンバは、クラス内部からのみアクセス可能で、派生クラスからはアクセスできません。

一方、protectedメンバは、クラス内部および派生クラスからアクセス可能です。

  • データの隠蔽: privateメンバは、外部からのアクセスを完全に制限するため、データの隠蔽が強化されます。

protectedメンバは、派生クラスからのアクセスを許可するため、データの隠蔽がやや緩やかです。

以下は、protectedprivateの違いをまとめた表です。

スクロールできます
特徴privateメンバprotectedメンバ
アクセス範囲クラス内部のみクラス内部および派生クラスから
外部からのアクセス不可不可
継承時のアクセス不可可能

静的メンバ(static)のアクセス

静的メンバ変数の定義方法

静的メンバ変数は、クラス内でstaticキーワードを使用して定義されます。

静的メンバ変数は、クラスの全インスタンスで共有され、クラスがインスタンス化される前にメモリに割り当てられます。

以下は、静的メンバ変数の定義方法の例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    static int staticVariable; // 静的メンバ変数の宣言
    static void displayVariable() { // 静的メンバ関数
        cout << "staticVariableの値: " << staticVariable << endl; // 静的メンバ変数へのアクセス
    }
};
int MyClass::staticVariable = 0; // 静的メンバ変数の初期化
int main() {
    MyClass::staticVariable = 10; // クラス名を通じて静的メンバ変数にアクセス
    MyClass::displayVariable(); // 静的メンバ関数の呼び出し
    return 0;
}
staticVariableの値: 10

静的メンバ関数の定義方法

静的メンバ関数も、クラス内でstaticキーワードを使用して定義されます。

静的メンバ関数は、インスタンスに依存せず、クラス名を通じて呼び出すことができます。

以下は、静的メンバ関数の定義方法の例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    static int staticVariable; // 静的メンバ変数の宣言
    static void setVariable(int value) { // 静的メンバ関数
        staticVariable = value; // 静的メンバ変数へのアクセス
    }
};
int MyClass::staticVariable = 0; // 静的メンバ変数の初期化
int main() {
    MyClass::setVariable(20); // 静的メンバ関数の呼び出し
    cout << "staticVariableの値: " << MyClass::staticVariable << endl; // 静的メンバ変数へのアクセス
    return 0;
}
staticVariableの値: 20

クラス変数を通じた静的メンバへのアクセス

静的メンバ変数は、クラスのインスタンスを通じてアクセスすることもできますが、一般的にはクラス名を通じてアクセスすることが推奨されます。

以下は、クラス変数を通じた静的メンバへのアクセスの例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    static int staticVariable; // 静的メンバ変数の宣言
    void setVariable(int value) { // インスタンスメンバ関数
        staticVariable = value; // 静的メンバ変数へのアクセス
    }
};
int MyClass::staticVariable = 0; // 静的メンバ変数の初期化
int main() {
    MyClass obj; // クラスのインスタンス生成
    obj.setVariable(30); // インスタンスメンバ関数の呼び出し
    cout << "staticVariableの値: " << MyClass::staticVariable << endl; // 静的メンバ変数へのアクセス
    return 0;
}
staticVariableの値: 30

クラス名を通じた静的メンバへのアクセス

静的メンバは、クラス名を通じて直接アクセスすることができます。

これは、静的メンバがクラスに属しているためです。

以下は、クラス名を通じた静的メンバへのアクセスの例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    static int staticVariable; // 静的メンバ変数の宣言
    static void increment() { // 静的メンバ関数
        staticVariable++; // 静的メンバ変数へのアクセス
    }
};
int MyClass::staticVariable = 0; // 静的メンバ変数の初期化
int main() {
    MyClass::increment(); // 静的メンバ関数の呼び出し
    cout << "staticVariableの値: " << MyClass::staticVariable << endl; // 静的メンバ変数へのアクセス
    return 0;
}
staticVariableの値: 1

静的メンバの初期化とスコープ

静的メンバ変数は、クラス内で宣言されるだけでは初期化されません。

クラス外で初期化を行う必要があります。

静的メンバ変数の初期化は、通常、クラス名を使って行います。

また、静的メンバは、プログラム全体で共有されるため、スコープはクラスに限定されません。

以下は、静的メンバの初期化とスコープの例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    static int staticVariable; // 静的メンバ変数の宣言
    static void reset() { // 静的メンバ関数
        staticVariable = 0; // 静的メンバ変数へのアクセス
    }
};
int MyClass::staticVariable = 5; // 静的メンバ変数の初期化
int main() {
    cout << "初期値: " << MyClass::staticVariable << endl; // 静的メンバ変数へのアクセス
    MyClass::reset(); // 静的メンバ関数の呼び出し
    cout << "リセット後の値: " << MyClass::staticVariable << endl; // 静的メンバ変数へのアクセス
    return 0;
}
初期値: 5
リセット後の値: 0

コンストラクタとデストラクタのアクセス

コンストラクタのアクセス修飾子

コンストラクタは、クラスのインスタンスが生成される際に呼び出される特別なメンバ関数です。

コンストラクタには、publicprivateprotectedのアクセス修飾子を指定することができます。

publicコンストラクタは、クラスの外部からインスタンスを生成するために使用され、privateprotectedコンストラクタは、特定の条件下でのみインスタンスを生成できるように制限します。

以下は、publicコンストラクタの例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    MyClass() { // publicコンストラクタ
        cout << "インスタンスが生成されました。" << endl;
    }
};
int main() {
    MyClass obj; // インスタンス生成
    return 0;
}
インスタンスが生成されました。

デストラクタのアクセス修飾子

デストラクタは、クラスのインスタンスが破棄される際に呼び出される特別なメンバ関数です。

デストラクタもコンストラクタと同様に、publicprivateprotectedのアクセス修飾子を指定できます。

publicデストラクタは、インスタンスが外部から破棄される際に使用され、privateデストラクタは、特定の条件下でのみインスタンスを破棄できるように制限します。

以下は、publicデストラクタの例です。

#include <iostream>
using namespace std;
class MyClass {
public:
    ~MyClass() { // publicデストラクタ
        cout << "インスタンスが破棄されました。" << endl;
    }
};
int main() {
    MyClass obj; // インスタンス生成
    return 0; // インスタンスが破棄される
}
インスタンスが破棄されました。

privateコンストラクタの使い方

privateコンストラクタは、クラスの外部からインスタンスを生成できないようにするために使用されます。

これにより、クラスのインスタンス生成を制御することができます。

以下は、privateコンストラクタの例です。

#include <iostream>
using namespace std;
class MyClass {
private:
    MyClass() { // privateコンストラクタ
        cout << "インスタンスが生成されました。" << endl;
    }
public:
    static MyClass createInstance() { // インスタンス生成を制御する静的メンバ関数
        return MyClass(); // privateコンストラクタを呼び出す
    }
};
int main() {
    MyClass obj = MyClass::createInstance(); // 静的メンバ関数を通じてインスタンス生成
    return 0;
}
インスタンスが生成されました。

シングルトンパターンにおけるprivateコンストラクタ

シングルトンパターンは、クラスのインスタンスが1つだけであることを保証するデザインパターンです。

このパターンでは、privateコンストラクタを使用して、外部からのインスタンス生成を防ぎます。

以下は、シングルトンパターンの実装例です。

#include <iostream>
using namespace std;
class Singleton {
private:
    static Singleton* instance; // インスタンスを保持するポインタ
    Singleton() { // privateコンストラクタ
        cout << "シングルトンインスタンスが生成されました。" << endl;
    }
public:
    static Singleton* getInstance() { // インスタンスを取得する静的メンバ関数
        if (instance == nullptr) {
            instance = new Singleton(); // インスタンスが存在しない場合に生成
        }
        return instance; // インスタンスを返す
    }
};
Singleton* Singleton::instance = nullptr; // インスタンスの初期化
int main() {
    Singleton* obj1 = Singleton::getInstance(); // シングルトンインスタンスの取得
    Singleton* obj2 = Singleton::getInstance(); // 同じインスタンスを取得
    return 0;
}
シングルトンインスタンスが生成されました。

この例では、getInstanceメソッドを通じてのみインスタンスを取得でき、privateコンストラクタにより外部からのインスタンス生成が防がれています。

応用例:アクセス修飾子を活用した設計

カプセル化の実現

カプセル化は、オブジェクト指向プログラミングの基本的な概念であり、データとその操作を一つの単位としてまとめることを指します。

アクセス修飾子を使用することで、クラスの内部状態を隠蔽し、外部からの不正なアクセスを防ぐことができます。

以下は、カプセル化の実現例です。

#include <iostream>
using namespace std;
class BankAccount {
private:
    double balance; // 残高を保持するprivateメンバ変数
public:
    BankAccount(double initialBalance) : balance(initialBalance) {} // コンストラクタ
    void deposit(double amount) { // 入金メソッド
        if (amount > 0) {
            balance += amount; // 残高を増加
        }
    }
    void withdraw(double amount) { // 出金メソッド
        if (amount > 0 && amount <= balance) {
            balance -= amount; // 残高を減少
        }
    }
    double getBalance() const { // 残高取得メソッド
        return balance; // 残高を返す
    }
};
int main() {
    BankAccount account(1000.0); // 銀行口座のインスタンス生成
    account.deposit(500.0); // 入金
    account.withdraw(200.0); // 出金
    cout << "残高: " << account.getBalance() << endl; // 残高の表示
    return 0;
}
残高: 1300

継承とアクセス修飾子の組み合わせ

継承を使用することで、基底クラスの機能を派生クラスに引き継ぐことができます。

アクセス修飾子を適切に使用することで、基底クラスのメンバへのアクセスを制御し、派生クラスでの利用を制限することができます。

以下は、継承とアクセス修飾子の組み合わせの例です。

#include <iostream>
using namespace std;
class BaseClass {
protected:
    int protectedVariable; // protectedメンバ変数
public:
    BaseClass(int value) : protectedVariable(value) {} // コンストラクタ
};
class DerivedClass : public BaseClass { // BaseClassを継承
public:
    DerivedClass(int value) : BaseClass(value) {} // コンストラクタ
    void displayVariable() { // publicメンバ関数
        cout << "protectedVariableの値: " << protectedVariable << endl; // 基底クラスのprotectedメンバへのアクセス
    }
};
int main() {
    DerivedClass obj(500); // 派生クラスのインスタンス生成
    obj.displayVariable(); // 派生クラスのpublicメンバ関数の呼び出し
    return 0;
}
protectedVariableの値: 500

フレンド関数を使った特定のアクセス許可

フレンド関数を使用することで、特定の関数に対してクラスのprivateメンバやprotectedメンバへのアクセスを許可することができます。

これにより、特定の関数がクラスの内部状態にアクセスできるようになります。

以下は、フレンド関数を使った特定のアクセス許可の例です。

#include <iostream>
using namespace std;
class MyClass {
private:
    int privateVariable; // privateメンバ変数
public:
    MyClass(int value) : privateVariable(value) {} // コンストラクタ
    friend void displayPrivateVariable(MyClass& obj); // フレンド関数の宣言
};
void displayPrivateVariable(MyClass& obj) { // フレンド関数
    cout << "privateVariableの値: " << obj.privateVariable << endl; // privateメンバへのアクセス
}
int main() {
    MyClass obj(100); // クラスのインスタンス生成
    displayPrivateVariable(obj); // フレンド関数の呼び出し
    return 0;
}
privateVariableの値: 100

インターフェースクラスとアクセス修飾子

インターフェースクラスは、純粋仮想関数を持つクラスであり、他のクラスがそのインターフェースを実装することを強制します。

インターフェースクラスのメンバ関数は通常publicとして定義され、実装クラスでのアクセスを許可します。

以下は、インターフェースクラスとアクセス修飾子の例です。

#include <iostream>
using namespace std;
class IShape { // インターフェースクラス
public:
    virtual void draw() = 0; // 純粋仮想関数
};
class Circle : public IShape { // IShapeを実装
public:
    void draw() override { // drawメソッドの実装
        cout << "円を描画しました。" << endl;
    }
};
int main() {
    Circle circle; // Circleのインスタンス生成
    circle.draw(); // drawメソッドの呼び出し
    return 0;
}
円を描画しました。

シングルトンパターンの実装

シングルトンパターンは、クラスのインスタンスが1つだけであることを保証するデザインパターンです。

このパターンでは、privateコンストラクタを使用して、外部からのインスタンス生成を防ぎます。

以下は、シングルトンパターンの実装例です。

#include <iostream>
using namespace std;
class Singleton {
private:
    static Singleton* instance; // インスタンスを保持するポインタ
    Singleton() { // privateコンストラクタ
        cout << "シングルトンインスタンスが生成されました。" << endl;
    }
public:
    static Singleton* getInstance() { // インスタンスを取得する静的メンバ関数
        if (instance == nullptr) {
            instance = new Singleton(); // インスタンスが存在しない場合に生成
        }
        return instance; // インスタンスを返す
    }
};
Singleton* Singleton::instance = nullptr; // インスタンスの初期化
int main() {
    Singleton* obj1 = Singleton::getInstance(); // シングルトンインスタンスの取得
    Singleton* obj2 = Singleton::getInstance(); // 同じインスタンスを取得
    return 0;
}
シングルトンインスタンスが生成されました。

この例では、getInstanceメソッドを通じてのみインスタンスを取得でき、privateコンストラクタにより外部からのインスタンス生成が防がれています。

よくある質問

privateメンバにアクセスする方法は?

privateメンバには、クラスの外部から直接アクセスすることはできませんが、以下の方法でアクセスすることができます。

  • 公のメンバ関数を通じてアクセス: privateメンバにアクセスするための公のメンバ関数を定義し、その関数を呼び出すことで間接的にアクセスできます。
  • フレンド関数を使用: フレンド関数を定義することで、その関数にprivateメンバへのアクセス権を与えることができます。

フレンド関数は、クラスの外部に定義されますが、特定のクラスのprivateメンバにアクセスできます。

例:obj.setVariable(10);のように公のメンバ関数を通じてアクセスすることが一般的です。

protectedメンバはいつ使うべき?

protectedメンバは、クラスの内部およびその派生クラスからアクセス可能です。

以下のような場合に使用することが推奨されます。

  • 継承を利用する場合: 基底クラスのメンバを派生クラスで利用したいが、外部からのアクセスを制限したい場合にprotectedを使用します。
  • クラスの拡張性を考慮する場合: 将来的にクラスを拡張する可能性がある場合、protectedメンバを使用することで、派生クラスが基底クラスの機能を利用できるようにします。

静的メンバと通常のメンバの違いは?

静的メンバと通常のメンバの主な違いは以下の通りです。

  • メモリの割り当て: 静的メンバはクラスに属し、全てのインスタンスで共有されます。

一方、通常のメンバは各インスタンスごとに異なるメモリ領域を持ちます。

  • アクセス方法: 静的メンバはクラス名を通じてアクセスすることが一般的で、インスタンスを介さずにアクセスできます。

通常のメンバは、インスタンスを通じてアクセスする必要があります。

  • ライフサイクル: 静的メンバはプログラムの実行中に一度だけ初期化され、プログラムが終了するまで存在します。

通常のメンバは、インスタンスが生成されるときに初期化され、インスタンスが破棄されるときに消失します。

まとめ

この記事では、C++におけるクラスメンバのアクセス修飾子について詳しく解説し、publicprivateprotectedの違いや、それぞれのメンバへのアクセス方法、静的メンバの扱い、コンストラクタやデストラクタのアクセス修飾子の役割について触れました。

これらの知識を活用することで、より安全で拡張性のあるプログラム設計が可能になります。

今後は、実際のプロジェクトにおいてこれらの概念を適用し、効果的なクラス設計を行ってみてください。

  • URLをコピーしました!
目次から探す