このブログ記事では、C++におけるアクセス指定子の仕組みを紹介します。

Public & Private アクセス指定子
前回の記事で、属性やメソッドを定義するときに使用する public
キーワードについて簡単に触れましたが、
これはアクセス指定子の1つであり、属性やメソッドを外部からアクセス可能にするものです。したがって、
publicアクセス指定子を使うと、次のようなコードを書くことができます。
class Class {
public:
string public_attr;
void public_print() {
cout << "Public Method" << endl;
};
};
int main () {
Class public;
public.public_attr = "Public";
cout << public.public_attr << endl; // => Public
public.public_print(); // => Public Method
return 0;
}
しかし、場合によっては外部からのアクセスを許可したくないこともあります。たとえば、ユーザーのパスワードや暗号化アルゴリズムを公開するのは望ましくありません。 このような場合には、privateアクセス指定子を使用できます。
class BankAccount {
public:
string name;
int set_password(string password) {
string encrypted = this -> encrypt(password);
this -> password = encrypted;
return 1;
};
private:
string password;
string encrypt(string password) {
// Encryption
};
};
int main () {
BankAccount user;
user.name = "TK";
user.password = "abcdefg"; // => Err
user.set_password("abcdefg");
user.encrypt("abcdefg"); // => Err
return 0;
};
privateアクセス指定子は内部の属性やメソッドを外部から隠すため、カプセル化と関心の分離を実現できます。 たとえば、機械学習モデルを構築する際、モデルの重みやバイアスはprivateアクセス指定子を使用して、 トレーニングを通じてのみ変更できるようにすることができます。
ユーザーがモデルの重みやバイアスにアクセスしたい場合は、それらを適切にフォーマットするpublicなgetter関数を介して行うべきです。 初期化するときには、ユーザーが手動で初期化する代わりに、適切に初期化するsetter関数を使用するべきです。
Protected アクセス指定子
BankAccount
クラスをABC銀行のABCBankAccount
クラスとして継承する際、BankAccount
のprivate属性にはアクセスできません。
class ABCBankAccount : public BankAccount {
public:
float balance;
ABCBankAccount(string name, string password) : name(name) {
string encrypted = this -> encrypt(password); // => Err
this -> password = encrypted; // => Err
balance = 0;
;}
};
これは、privateアクセス指定子が外部からのアクセスを子クラスも含めて禁止するためです。 子クラスにアクセスを許可しながら外部からのアクセスを防ぐには、protectedアクセス指定子を使用できます。
class BankAccount {
public:
string name;
int set_password(string password) {
string encrypted = this -> encrypt(password);
this -> password = encrypted;
return 1;
};
protected:
string password;
string encrypt(string password) {
// Encryption
};
};
class ABCBankAccount : public BankAccount {
public:
float balance;
ABCBankAccount(string name, string password) : name(name) {
string encrypted = this -> encrypt(password); // => OK
this -> password = encrypted; // => OK
balance = 0;
;}
};
int main () {
ABCBankAccount user("TK", "abcdefg");
cout << user.password << endl; // => Err
user.encrypt("abcdefg"); // => Err
return 0;
}
基底クラスのアクセス指定子
クラスの継承を使用するときに、class ABCBankAccount : public BankAccount
のようにpublic
キーワードが使われているのを見たことがあるかもしれません。
ここでのpublic
は基底クラスのアクセス指定子と呼ばれ、基底クラスの属性やメソッドが子クラスにどのように継承されるかを決定します。
以下の表は、基底クラスのアクセス指定子に応じてメンバーのアクセスレベルがどのように変わるかを示しています。
基底クラスのアクセス指定子 | 基底クラスのPublicメンバー | 基底クラスのProtectedメンバー | 基底クラスのPrivateメンバー |
---|---|---|---|
public | Public | Protected | アクセス不可 |
protected | Protected | Protected | アクセス不可 |
private | Private | Private | アクセス不可 |
ご覧のとおり、基底クラスのprivateメンバーは、基底クラスのアクセス指定子に関係なく、子クラスを含めて誰からもアクセスできません。 しかし、publicとprotectedメンバーのアクセスレベルは、基底クラスのアクセス指定子によって変わります。
基底クラスのアクセス指定子がpublic
の場合、基底クラスのpublicおよびprotectedメンバーは子クラスでも同じアクセスレベルを維持します。
一方で、基底クラスのアクセス指定子がprotected
やprivate
の場合、基底クラスのpublic
およびprotected
メンバーは、
子クラス内でそれぞれprotected
またはprivate
に変更されます。(基底クラスのアクセス指定子を指定しない場合、デフォルトではprivate
になります。)
リソース
- Portfolio Courses. 2022. Base Class Access Specifiers | C++ Tutorial. YouTube.
- Portfolio Courses. 2022. Protected Class Members | C++ Tutorial. YouTube.
- Portfolio Courses. 2022. Public And Private Access Specifiers | C++ Tutorial. YouTube.