「C++言語」の「カプセル化」とクラスへの「アクセス権限」について学ぼう!!
今回は「クラスのメンバ」に「アクセス権限」を設定し、自由に「クラスのメンバ」にアクセスができないように設定をする方法について学んでいきたいと思います。
「オブジェクトのデータ」を安全な状態に保つために重要な機能なのですが、仕組みが複雑そうなので、ゆっくりと学習を進めていきます。
「C++言語」にはまだまだたくさん機能があるのかな~そろそろ頭の容量がいっぱいに・・・
「private」と「public」の宣言の違いと「カプセル化」の考え方
「クラスのメンバ」には「公開範囲」を設定することができ、「外部に公開するメンバ」は「public」に記述し、「外部に公開しないメンバ」は「private」に設定をします。
class クラス名 { public: // 外部に公開するメンバを記述 private: // 外部に公開しないメンバを記述 };
クラスを作ってみると、
//「マンション」クラスを定義 class Mansion{ public: int floor; // 階数 int price; // 販売価格 private: };
のように作成した場合、マンションの「階数」と「販売価格」のメンバが「外部から自由に変更できるオブジェクト」ができてしまいます・・・怖いですね。
そのため、通常は、
//「マンション」クラスを定義 class Mansion{ public: private: int floor; // 階数 int price; // 販売価格 };
のように「private」にメンバを作成します。
言葉だけだとわかりにくいので、図にしてみると、
のようになり、外部のクラスから「public」の領域にはアクセスができますが、「private」の領域へはアクセスができません。
「メンバのデータ」を守るために必要な仕組みでもあったんですね。
でも、もし外部のクラスから「privateメンバ」にアクセスする必要がある場合はどのようにすればいいのでしょうか?
例えば、「privateメンバ」に格納されている値を取得したい場合に、取得する手段が無いため、「利用できないデータ」になってしまいます。
そこでいろいろと調べてみたら、「ゲッター」と呼ばれる関数を「public」で作ると、「privateメンバ」の値を取得できるようになるそうです。
Getter(ゲッター)
「ゲッター」は「public」に作成していきますが、名前の付け方はいろいろな方法があるようです。
今回はメンバの先頭に「get」を付ける方法を利用していきたいと思います。
「ゲッター」を利用したプログラムは、
#include <iostream> #include <string> using namespace std; //「マンション」クラスを定義 class Mansion{ public: // コンストラクタ Mansion(int floor_val, int price_val){ floor = floor_val; price = price_val; } //「プライベートメンバ(floor)」のゲッター int getFloor(){ return floor; } //「プライベートメンバ(price)」のゲッター int getPrice(){ return price; } private: int floor; int price; }; int main() { Mansion ms = Mansion(5, 1000000000); cout << ms.getFloor() << endl; return 0; }
のようになります。
このプログラムを実行すると、
5
と表示されます。
もし、間違って
cout << ms.floor << endl;
のように直接「プライベートメンバ」にアクセスをすると、
error: 'int Mansion::floor' is private within this context
のようなエラーメッセージが出て、怒られてしまいました。
なので、「プライベートメンバ」は安全だということが確認できました(笑)
値を取得することができるようになったのですが、「プライベートメンバ」に値を設定することはできません。・・・が、
「セッター」という関数を作ると値を設定することができるみたいです。
セッター
「セッター」は、「プライベート」なメンバに値を設定するための関数です。
しかし、この関数を公開してしまうと、勝手に値を書き換えられてしまう危険性が生まれてしまうので、作る時には慎重に検討する必要があります。
「セッター」の名前は「set」の次にメンバの名前を付加していきます。プログラムを作ると・・・
#include <iostream> #include <string> using namespace std; //「マンション」クラスを定義 class Mansion{ public: // コンストラクタ Mansion(int floor_val, int price_val){ floor = floor_val; price = price_val; } //「プライベートメンバ(floor)」のゲッター int getFloor(){ return floor; } //「プライベートメンバ(price)」のゲッター int getPrice(){ return price; } //「プライベートメンバ(floor)」のセッター void setFloor(int floor_val){ floor = floor_val; } //「プライベートメンバ(price)」のセッター void setPrice(int price_val){ price = price_val; } private: int floor; int price; }; int main() { Mansion ms = Mansion(5, 1000000000); cout << ms.getFloor() << endl; // 「セッター」で「floor」を変更 ms.setFloor(7); cout << ms.getFloor() << endl; return 0; }
これを実行すると、
5 7
のように表示され、「セッター」で「floorメンバ」の値が変更できているのがわかりますね。
ただ、どんなクラスでも「メンバ」にアクセスできるのは危ない気がします。
「カプセル化」の考え方
「カプセル化」は、「メンバを守るための仕組み」ですが、メンバに「private」を指定することで、外部からのアクセスを防ぐことができます。
「クラス」が持っておくデータ(メンバ)は、すべて「private」に設定し、外部からメンバを変更されないように守る仕組みを「カプセル化」と呼んでいるそうです。
「カプセル」が「private」のメンバを囲んで守っているようなイメージなんですね。
他のプログラム言語でも、同様の考え方でプログラミングを行うこともできるとのことでした。
どんどん複雑な仕組みが出てきていて、だいぶ混乱してきていますが、少しずつ内容を整理しながら学習を進めていきたいと思います。
→(前へ)「C++言語」の「コンストラクタ」の仕組みと使い方
→(次へ)「C言語」の「デストラクタ・インライン関数・静的メンバ」を勉強しよう!