はじめに
オブジェクト指向プログラミングの三本柱の一つである「カプセル化 (Encapsulation)」は、**データ(メンバ変数)と、それを操作する手続き(メンバ関数)**を一つにまとめ、重要なデータを外部から守るための仕組みです。
C++では、アクセス指定子(public
, private
, protected
)を使うことで、このカプセル化を実現します。これにより、オブジェクトの利用者は、知る必要のない内部構造を意識することなく、公開された安全な窓口(メンバ関数)だけを使ってオブジェクトを操作できます。
この記事では、3種類のアクセス指定子の役割と、カプセル化がなぜ重要なのかを、具体的なサンプルコードと共に解説します。
アクセス指定子の種類と役割
アクセス指定子は、クラスのメンバが、クラスの外部からアクセスできるかどうかを制御します。
public:
: 公開。public:
以降に宣言されたメンバは、クラスの外部から誰でも自由にアクセスできます。private:
: 非公開。private:
以降に宣言されたメンバは、そのクラスの内部にあるメンバ関数からしかアクセスできません。外部からは完全に隠されます。クラスでアクセス指定子を省略した場合、デフォルトでprivate
になります。protected:
:private
に似ていますが、継承された子クラスからはアクセスが許可される、という特徴があります。
カプセル化の実践サンプルコード
このコードは、BankAccount
(銀行口座)クラスを例に、口座残高(balance
)を private
にして外部から直接変更できないように保護し、public
なメンバ関数(deposit
, withdraw
, getBalance
)を通じてのみ、安全に操作できるようにしています。
完成コード
#include <iostream>
#include <string>
using namespace std;
class BankAccount {
private:
// メンバ変数をprivateで宣言し、外部から隠蔽する
string ownerName; // 口座名義人
long balance; // 残高
public:
// コンストラクタ(オブジェクト作成時の初期化処理)
BankAccount(string name, long initialDeposit) {
ownerName = name;
balance = initialDeposit;
}
// publicなメンバ関数を、操作のための窓口として公開する
void deposit(long amount) { // 入金
if (amount > 0) {
balance += amount;
cout << amount << "円を入金しました。残高: " << balance << "円" << endl;
}
}
void withdraw(long amount) { // 出金
if (amount > 0 && balance >= amount) {
balance -= amount;
cout << amount << "円を出金しました。残高: " << balance << "円" << endl;
} else {
cout << "出金できませんでした。" << endl;
}
}
long getBalance() { // 残高照会
return balance;
}
};
int main() {
// BankAccountオブジェクトを作成
BankAccount myAccount("山田 太郎", 50000);
// publicなメンバ関数経由で操作
myAccount.deposit(10000);
myAccount.withdraw(5000);
// privateなメンバ変数に直接アクセスしようとすると、コンパイルエラーになる
// myAccount.balance = 999999; // エラー! balanceはprivateです
cout << "最終残高: " << myAccount.getBalance() << "円" << endl;
return 0;
}
コードの解説とカプセル化の目的
データの隠蔽
balance
(残高)という非常に重要なデータは private
で宣言されています。これにより、main
関数の中から myAccount.balance = 999999;
のように、値を直接、不正に書き換えることができなくなります。
公開された操作の窓口
balance
を変更する唯一の方法は、public
で公開された deposit
(入金)や withdraw
(出金)といったメンバ関数を呼び出すことです。
カプセル化の目的
なぜこのようなことをするのでしょうか?それは、オブジェクトの安全性を保つためです。 withdraw
関数の中には、balance >= amount
というチェックがあり、残高以上の金額は引き出せないようになっています。もし balance
が public
で、誰でも直接変更できてしまったら、この重要なチェックを無視して、残高をマイナスにすることも可能になってしまいます。
このように、カプセル化は、クラスの作者が意図した、安全で正しい方法でしかデータが操作されないことを保証するための、非常に重要な仕組みなのです。これにより、クラスの利用者は、その内部の詳細を気にすることなく、安心してそのクラス(オブジェクト)を使うことができます。
まとめ
今回は、オブジェクト指向の重要な柱である「カプセル化」と、それを実現するためのアクセス指定子について解説しました。
- カプセル化とは、データと操作をまとめ、データを外部から保護(隠蔽)する仕組み。
private
: メンバを隠す。クラス内部からのみアクセス可。public
: メンバを公開する。外部からの操作の窓口となる。protected
:private
に近いが、子クラスからのアクセスを許可する(継承で利用)。
メンバ変数は原則として private
にし、それらを操作するための public
なメンバ関数を提供する、という設計が、カプセル化の基本であり、高品質で再利用しやすいクラスを作成するための第一歩です。