Menu
Coddy logo textTech

アクセス指定子の詳細

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 を記述することを推奨しています。

challenge icon

チャレンジ

簡単

同じクラスのオブジェクト同士が互いの private メンバーにアクセスできる仕組みを示す、Wallet の比較システムを作りましょう。これは C++ のアクセス制御に関する重要なポイントです。アクセス制御はオブジェクト単位ではなく、class 単位で適用されます。

コードを整理するために、2 つのファイルを作成します。

  • Wallet.h:private の財務データを保持しながら、Wallet 同士の比較を可能にする Wallet class を定義します。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 変更します
  • 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" を出力する(結果が変わる可能性があります)

ここでの key concept は、hasMoreThan()transferTo() のようなメソッドが、別の Wallet オブジェクトの private メンバーである balance に directly access できることです。getter は必要ありません。これは C++ の access control が class-based だからです。Wallet class 内のあらゆるコードは、anyWallet オブジェクトの private メンバーにアクセスできます。

すべての金額を小数点以下 2 桁で Format するには、<iomanip>std::fixedstd::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;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: C++オンラインコンパイラ