基底クラスと派生クラスへのアクセス
メンバーのスコープ:インデックス への移動
派生クラス D を宣言する際は、基底クラス B1、B2、... をコンマで区切って並べて、基底リストとします。
class-key D : base-list { <member-list> }
D は、これら基底クラスのすべてのメンバを継承します。なお、再定義された基底クラス メンバも継承され、必要に応じてスコープ オーバーライドを用いてアクセスすることができます。D は、自分の基底クラスの public メンバと protected メンバのみ使用できます。しかし、D から見た場合、継承メンバのアクセス属性はどうなるのでしょうか。たとえば、D では基底クラスの特定の public メンバを使用したいが、外部の関数に関する限りは、そのメンバを private にしたいとしましょう。これを解決するには、基底リストでアクセス指定子を使用します。
メモ: 基底クラス自身が派生クラスになり得るので、アクセス属性の問題は再帰的です。つまり、継承するものがない最上位の基底クラスに達するまで、継承階層をさかのぼります。
D を宣言する際に、次のように、基底リスト内のクラスの前にアクセス指定子 public、protected、private のいずれかを付けることができます。
class D : public B1, private B2 /* , … */ {
// …
}
これらの修飾子は、基底クラスから見た場合の基底メンバのアクセス属性を変更するわけではなく、派生クラスから見た場合の基底メンバのアクセス属性を変更することができるのです。
D がクラス宣言であればデフォルトは private であり、D が構造体宣言であればデフォルトは public です。
メモ: 共用体は基底クラスを持つことができず、共用体を基底クラスとして使用することもできません。
派生クラスは、基底クラスからアクセス属性を次のように継承します。
- public 基底クラス: 基底クラスの public メンバーは、派生クラスの public メンバーになります。基底クラスの protected メンバーは、派生クラスの protected メンバーになります。 基底クラスの private メンバーは、基底クラスに対して private メンバーのままなります。
- protected 基底クラス: 基底クラスの public と protected のメンバーは両方とも、派生クラスの protected メンバーになります。基底クラスの private メンバーは、基底クラスに対して private メンバーのままなります。
- private 基底クラス: 基底クラスの public と protected のメンバーは両方とも、派生クラスの private メンバーになります。 基底クラスの private メンバーは、基底クラスに対して private メンバーのままなります。
基底クラスの private メンバは、基底クラスで friend 宣言が明示的に行われてアクセスが許可されない限り、派生クラスのメンバ関数からは絶対にアクセスできないことに注意してください。以下に例を示します。
/* class X is derived from class A */
class X : A { // default for class is private A
// …
}
/* class Y is derived (multiple inheritance) from B and C
B defaults to private B */
class Y : B, public C { // override default for C
// …
}
/* struct S is derived from D */
struct S : D { // default for struct is public D
// …
}
/* struct T is derived (multiple inheritance) from D and E
E defaults to public E */
struct T : private D, E { // override default for D
// E is public by default
// …
}
基底リスト内のアクセス指定子の効果は、派生クラスの public または protected 宣言で修飾名を使って調整することができます。以下に例を示します。
class B {
int a; // private by default
public:
int b, c;
int Bfunc(void);
};
class X : private B { // a, b, c, Bfunc are now private in X
int d; // private by default, NOTE: a is not
// accessible in X
public:
B::c; // c was private, now is public
int e;
int Xfunc(void);
};
int Efunc(X& x); // external to B and X
関数 Efunc() では、public な名前である c、e、Xfunc() のみ使用できます。
関数 Xfunc() は、private B から派生した X に定義されているため、以下にアクセスできます。
- "調整されて public になった" c
- B のメンバのうち、"X に対して private な" もの: b と Bfunc()
- X 自身の private メンバおよび public メンバ: d、e、Xfunc()
ただし、Xfunc() は "B に対して private な" メンバである a にはアクセスできません。