アクセス指定子の詳細
CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 35/104。
3つのaccess指定子を理解したところで、同じclassの複数のオブジェクトがある場合に、それらがどのように動作するかを見ていきましょう。よくある誤解は、privateが「このオブジェクトだけ」を意味するというものです。しかし実際には、「このclassだけ」を意味します。
同じクラスのオブジェクトは、お互いの private メンバーにアクセスできます。
class Person {
std::string secret;
public:
Person(std::string s) : secret(s) {}
void readSecret(const Person& other) {
// 別のオブジェクトの private メンバーにアクセスしている - 許可されています!
std::cout << other.secret;
}
};これは、access 制御がオブジェクトレベルではなくclass レベルで適用されるためです。readSecretメソッドはPersonclassの一部なので、任意のPersonオブジェクトのprivateメンバーにaccessできます。この設計により、コピーコンストラクターや比較演算子などの操作で、他のオブジェクトの内部状態を扱えるようになります。
クラス内では、アクセス指定子を複数回切り替えることもできます。
class Mixed {
public:
void publicMethod1();
private:
int privateData;
public:
void publicMethod2(); // public に戻る
private:
void privateHelper(); // 再び private
};これは有効な C++ ですが、可読性のために通常はアクセスレベルごとにメンバーをグループ化する方がよいでしょう。ほとんどのスタイルガイドでは、public メンバー(クラスのインターフェースを形成するため)を最初に記述し、続いて protected、最後に private を記述することを推奨しています。
チャレンジ
簡単同じクラスのオブジェクト同士が互いの private メンバーにアクセスできる仕組みを示す、Wallet の比較システムを作りましょう。これは C++ のアクセス制御に関する重要なポイントです。アクセス制御はオブジェクト単位ではなく、class 単位で適用されます。
コードを整理するために、2 つのファイルを作成します。
Wallet.h:private の財務データを保持しながら、Wallet 同士の比較を可能にするWalletclass を定義します。class には次の要素を含めます。- private メンバー:
ownerName(string)とbalance(double) - 所有者の名前と initial balance を受け取るコンストラクター
- 所有者の名前を返す public getter
getOwnerName() - この Wallet の balance と別の Wallet の private balance を比較し、この Wallet の金額が多い場合に
trueを返すメソッドhasMoreThan(const Wallet& other) - 両方の Wallet の private balance の合計を返すメソッド
combinedBalance(const Wallet& other) - この Wallet から別の Wallet へ金額を移動するメソッド
transferTo(Wallet& other, double amount)。amount が正で、この Wallet の balance を exceed しない場合に限り、両方の Wallet の private balance を directly 変更します
- private メンバー:
main.cpp:オブジェクトをまたいだ private メンバーへのアクセスを実演します。input から 2 つの所有者名と 2 つの balance(4 行:name1、balance1、name2、balance2)を読み取り、次の処理を行います。- input の値を使って 2 つの
Walletオブジェクトを Create する combinedBalance()を使って"Combined wealth: $<amount>"を出力する- Wallet を比較し、balance が高い所有者に対して
"<name> has more money"を出力する(判定にはhasMoreThan()を使用する) 100.0を first の Wallet から second の Wallet へ、transferTo()を使って移動する"After transfer:"を出力する"Combined wealth: $<amount>"をagain 出力する(値は unchanged のはずです)- again 比較し、
"<name> has more money"を出力する(結果が変わる可能性があります)
- input の値を使って 2 つの
ここでの key concept は、hasMoreThan() や transferTo() のようなメソッドが、別の Wallet オブジェクトの private メンバーである balance に directly access できることです。getter は必要ありません。これは C++ の access control が class-based だからです。Wallet class 内のあらゆるコードは、any の Wallet オブジェクトの private メンバーにアクセスできます。
すべての金額を小数点以下 2 桁で Format するには、<iomanip> の std::fixed と std::setprecision(2) を使用します。balance の input は std::stod() を使って変換します。
自分で試してみよう
#include <iostream>
#include <string>
#include <iomanip>
#include "Wallet.h"
using namespace std;
int main() {
// 入力を読み取る: name1, balance1, name2, balance2
string name1, name2;
string balanceStr1, balanceStr2;
getline(cin, name1);
getline(cin, balanceStr1);
getline(cin, name2);
getline(cin, balanceStr2);
double balance1 = stod(balanceStr1);
double balance2 = stod(balanceStr2);
// 金額の出力フォーマットを設定する
cout << fixed << setprecision(2);
// TODO: 入力値で2つのWalletオブジェクトを作成する
// TODO: Print combined wealth using combinedBalance()
// Format: "Combined wealth: $<amount>"
// TODO: Compare wallets using hasMoreThan() and print who has more money
// Format: "<name> has more money"
// TODO: transferTo()を使って最初のウォレットから2番目へ100.0を送金する
// TODO: Print "After transfer:"
// TODO: Print combined wealth again
// TODO: Compare again and print who has more money
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
3コンストラクタとデストラクタ
デフォルトコンストラクタパラメータ付きコンストラクタコピーコンストラクタムーブコンストラクタコンストラクタ初期化リスト委譲コンストラクタデストラクタ徹底解説Rule of Three / Five / Zero復習 - Stringクラス6演算子オーバーロード
演算子オーバーロード入門算術演算子のオーバーロード比較演算子のオーバーロードストリーム演算子代入演算子のオーバーロード[] と () の演算子オーバーロード型変換演算子復習 - Matrixクラス自分で練習してみよう: C++オンラインコンパイラ