継承のアクセスレベル
CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 49/104。
選択した inheritance の型は、derived class で base class のメンバーにどのようにアクセスできるかに影響します。C++ では、public、protected、private inheritance の3つの選択肢があります。
各タイプがメンバーの access をどのように変換するかは次のとおりです:
| Base メンバー | public inheritance | protected inheritance | private inheritance |
|---|---|---|---|
| public | public | protected | private |
| protected | protected | protected | private |
| private | inaccessible | inaccessible | inaccessible |
class Base {
public:
int pub;
protected:
int prot;
private:
int priv;
};
class PublicDerived : public Base {
// pub は public、prot は protected、priv はアクセス不可
};
class ProtectedDerived : protected Base {
// pub は protected、prot は protected、priv はアクセス不可
};
class PrivateDerived : private Base {
// pub は private、prot は private、priv はアクセス不可
};Public inheritanceは「is-a」関係をモデル化するもので、はるかに最も一般的です。DogはAnimalなので、external codeはそれをAnimalとして扱えます。
protected と private inheritance model 「実装によって実現される」関係です。これらは base class のインターフェースを外部コードから隠すため、inheritance 関係を公開せずに実装を再利用したい場合に便利です。private inheritance では、さらに derived クラスでさえ、元の base メンバーへの access を失います。
チャレンジ
簡単異なる継承タイプがメンバーへのアクセス可能性にどのような影響を与えるかを、シンプルなデバイス階層を構築して見てみましょう。基本となる Device class と、異なる継承タイプをそれぞれ使用する3つの derived class を作成し、public、protected、private 継承によってメンバーへのアクセスがどのように変化するかを実際に確認します。
コードを2つのファイルに分けて整理します。
Device.h: 異なる access level にある3つのメンバーを持つ基本Deviceclass を define します。- public な
std::string model - protected な
int serialNumber - private な
int internalCode(デフォルトで999に設定) - 次を prints する public method
showModel():Model: <model>
次に、それぞれ異なる継承タイプを使用して
Deviceから継承する3つの derived class を Create します。PublicDevice(public inheritance を使用): 次を prints する methoddisplaySerial()を追加します:Serial: <serialNumber>ProtectedDevice(protected inheritance を使用): 次を prints する methoddisplaySerial()を追加します:Serial: <serialNumber>PrivateDevice(private inheritance を使用): 次を prints する methoddisplaySerial()を追加します:Serial: <serialNumber>
各 derived class には、model name と serial number を受け取り、model を base class に渡して serial number を設定する Constructor が必要です。
- public な
main.cpp: 2つの input を読み取ります(それぞれ別の行に入力)。- Model name(string)
- Serial number(integer)
同じ input values を使用して、各 derived type の object を1つずつ Create します。その後、access の違いを Demonstrate します。
PublicDeviceの場合:- object 上で直接
showModel()を Call します(public inheritance によって public のまま保たれるため動作します) modelに直接 access し、次を print します:Direct model access: <model>displaySerial()を Call します
ProtectedDeviceとPrivateDeviceの場合:displaySerial()のみを Call します(継承されたshowModel()とmodelは、外部からはもはや public に access できません)
出力形式:
--- PublicDevice --- Model: <model> Direct model access: <model> Serial: <serial> --- ProtectedDevice --- Serial: <serial> --- PrivateDevice --- Serial: <serial>
例えば、input が Laptop と 12345 の場合:
--- PublicDevice ---
Model: Laptop
Direct model access: Laptop
Serial: 12345
--- ProtectedDevice ---
Serial: 12345
--- PrivateDevice ---
Serial: 12345PublicDevice だけが、継承された public members への external access を許可していることに注目してください。他の継承タイプでは、base class の interface は外部 code から隠されますが、derived class は独自の method を通じて protected members に内部から access できます。
自分で試してみよう
#include <iostream>
#include <string>
#include "Device.h"
using namespace std;
int main() {
// 入力を読み取る
string modelName;
int serialNum;
getline(cin, modelName);
cin >> serialNum;
// TODO: 入力値を使って各派生型のオブジェクトを作成する
// PublicDevice pubDev(modelName, serialNum);
// ProtectedDevice protDev(modelName, serialNum);
// PrivateDevice privDev(modelName, serialNum);
// TODO: Demonstrate PublicDevice access
cout << "--- PublicDevice ---" << endl;
// - オブジェクトに対して直接 showModel() を呼び出す
// - Access model directly and print: Direct model access: <model>
// - displaySerial() を呼び出す
// TODO: Demonstrate ProtectedDevice access
cout << "--- ProtectedDevice ---" << endl;
// - displaySerial() のみを呼び出す(showModel と model は公開アクセスできない)
// TODO: Demonstrate PrivateDevice access
cout << "--- PrivateDevice ---" << endl;
// - displaySerial() のみを呼び出す(showModel と model は公開アクセスできない)
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
3コンストラクタとデストラクタ
デフォルトコンストラクタパラメータ付きコンストラクタコピーコンストラクタムーブコンストラクタコンストラクタ初期化リスト委譲コンストラクタデストラクタ徹底解説Rule of Three / Five / Zero復習 - Stringクラス6演算子オーバーロード
演算子オーバーロード入門算術演算子のオーバーロード比較演算子のオーバーロードストリーム演算子代入演算子のオーバーロード[] と () の演算子オーバーロード型変換演算子復習 - Matrixクラス自分で練習してみよう: C++オンラインコンパイラ