[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
メンバは、派生クラスからのアクセスを許可するため、データの隠蔽がやや緩やかです。
以下は、protected
とprivate
の違いをまとめた表です。
特徴 | 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
コンストラクタとデストラクタのアクセス
コンストラクタのアクセス修飾子
コンストラクタは、クラスのインスタンスが生成される際に呼び出される特別なメンバ関数です。
コンストラクタには、public
、private
、protected
のアクセス修飾子を指定することができます。
public
コンストラクタは、クラスの外部からインスタンスを生成するために使用され、private
やprotected
コンストラクタは、特定の条件下でのみインスタンスを生成できるように制限します。
以下は、public
コンストラクタの例です。
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass() { // publicコンストラクタ
cout << "インスタンスが生成されました。" << endl;
}
};
int main() {
MyClass obj; // インスタンス生成
return 0;
}
インスタンスが生成されました。
デストラクタのアクセス修飾子
デストラクタは、クラスのインスタンスが破棄される際に呼び出される特別なメンバ関数です。
デストラクタもコンストラクタと同様に、public
、private
、protected
のアクセス修飾子を指定できます。
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
コンストラクタにより外部からのインスタンス生成が防がれています。
よくある質問
まとめ
この記事では、C++におけるクラスメンバのアクセス修飾子について詳しく解説し、public
、private
、protected
の違いや、それぞれのメンバへのアクセス方法、静的メンバの扱い、コンストラクタやデストラクタのアクセス修飾子の役割について触れました。
これらの知識を活用することで、より安全で拡張性のあるプログラム設計が可能になります。
今後は、実際のプロジェクトにおいてこれらの概念を適用し、効果的なクラス設計を行ってみてください。