Menu
Coddy logo textTech

C++ のアクセス修飾子

CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 34/104。

C++には、クラスメンバに誰がアクセスできるかを制御する3つのアクセス修飾子があります:publicprotected、およびprivate。これらはカプセル化の基礎を形成します。

class Account {
public:
    std::string ownerName;      // どこからでもアクセス可能
    
protected:
    double interestRate;        // このクラスおよび派生クラスからアクセス可能
    
private:
    double balance;             // このクラス内からのみアクセス可能
};

Public メンバは、クラス内、派生クラス、および外部コードなど、どこからでもアクセスできます。Private メンバは最も制限が厳しく、そのクラス内からのみアクセス可能です。Protected はその中間に位置し、外部に対しては private のように振る舞いますが、派生クラスからはこれらのメンバにアクセスできます。

class Account {
private:
    double balance;
    
public:
    Account() : balance(0) {}
    
    void deposit(double amount) {
        balance += amount;    // OK - クラス内
    }
};

int main() {
    Account acc;
    acc.deposit(100);         // OK - depositはpublicです
    // acc.balance = 500;     // エラー - balanceはprivateです
}

デフォルトでは、アクセス修飾子が指定されていない場合、クラス内のすべてのメンバは private になります。これにより、何を公開すべきかを明示的に決定することが促されます。一般的な慣習としては、データメンバを private にし、それらと安全にやり取りするための public メソッドを提供することです。

challenge icon

チャレンジ

簡単

アクセス修飾子が誰が何にアクセスできるかをどのように制御するかを示す、シンプルな従業員管理システムを構築しましょう。一部のデータは完全にプライベート、一部は潜在的なサブクラスからアクセス可能、そして一部は誰にでも公開されているクラスを作成します。

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

  • Employee.h: データを適切に保護するために3つすべてのアクセス修飾子を使用する Employee クラスを定義します:
    • Public: 従業員の name (string) — どこからでもアクセス可能です
    • Protected: 従業員の department (string) — クラス内および派生クラスからはアクセス可能ですが、外部からはアクセスできません
    • Private: 従業員の salary (double) — クラス内からのみアクセス可能です
    • 3つのメンバーすべてを初期化するために、名前、部署、給与を受け取るコンストラクタ
    • プライベートな給与の値を返すパブリックメソッド getSalary()
    • プロテクトされた部署の値を返すパブリックメソッド getDepartment()
    • 指定された額だけ給与を増やすパブリックメソッド giveRaise(double amount) (額が正の場合のみ)
    • 従業員の情報を次の形式で表示するパブリックメソッド displayInfo(): "Name: <name>, Department: <department>, Salary: "Name: , Department: , Salary: $"lt;salary>"
  • main.cpp: Employee オブジェクトを操作することで、アクセス修飾子がどのように機能するかを示します。入力から従業員の名前、部署、給与を(3つの別々の行で)読み取り、その後:
    • 入力値を使用して Employee を作成します
    • パブリックメンバーに直接アクセスして、従業員の名前を表示します: "Direct access - Name: <name>"
    • ゲッターを使用して部署を表示します: "Via getter - Department: <department>"
    • ゲッターを使用して給与を表示します: "Via getter - Salary: "Via getter - Salary: $"lt;salary>"
    • 従業員に 5000.0 の昇給を与えます
    • "After raise:" と表示します
    • displayInfo() を呼び出して、更新された情報を表示します

すべての給与値は、<iomanip>std::fixedstd::setprecision(2) を使用して小数点以下2桁でフォーマットしてください。給与の入力は std::stod() を使用して文字列から double に変換してください。

ここでの重要な洞察は、main から name には直接アクセスできますが、departmentsalary には直接アクセスできないということです。これらにはパブリックなゲッターメソッドを使用する必要があります。これがカプセル化の実際です。クラスがそのデータのアクセス方法と変更方法を制御します。

チートシート

C++には、クラスメンバへのアクセスを制御するための3つのアクセス修飾子が用意されています。

  • public: どこからでもアクセス可能
  • protected: クラス内および派生クラス内からアクセス可能
  • private: クラス内からのみアクセス可能
class Account {
public:
    std::string ownerName;      // Accessible from anywhere
    
protected:
    double interestRate;        // Accessible in this class and derived classes
    
private:
    double balance;             // Accessible only within this class
};

デフォルトでは、修飾子が指定されていない場合、クラス内のすべてのメンバはprivateになります。

アクセス制御を示す例:

class Account {
private:
    double balance;
    
public:
    Account() : balance(0) {}
    
    void deposit(double amount) {
        balance += amount;    // OK - inside the class
    }
};

int main() {
    Account acc;
    acc.deposit(100);         // OK - deposit is public
    // acc.balance = 500;     // ERROR - balance is private
}

ベストプラクティス:データメンバをprivateにし、それらと安全に対話するためのpublicメソッドを提供してください。

自分で試してみよう

#include <iostream>
#include <string>
#include <iomanip>
#include "Employee.h"

using namespace std;

int main() {
    // 入力を読み込む
    string name;
    string department;
    string salaryStr;
    
    getline(cin, name);
    getline(cin, department);
    getline(cin, salaryStr);
    double salary = stod(salaryStr);
    
    // 給与出力の精度を設定する
    cout << fixed << setprecision(2);
    
    // TODO: 入力値を使用して Employee オブジェクトを作成する
    
    // TODO: public メンバに直接アクセスして従業員の名前を出力する
    // Format: "Direct access - Name: <name>"
    
    // TODO: getter メソッドを使用して部署を出力する
    // Format: "Via getter - Department: <department>"
    
    // TODO: getter メソッドを使用して給与を出力する
    // Format: "Via getter - Salary: $<salary>"
    
    // TODO: 従業員に 5000.0 の昇給を行う
    
    // TODO: "After raise:" を出力する
    
    // TODO: displayInfo() を呼び出して更新された情報を表示する
    
    return 0;
}
quiz icon腕試し

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

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