Access specifiers
class/struct または union の member-specification において、後続のメンバーのアクセシビリティを定義します。
派生クラス の宣言における base-specifier で、後続の基底クラスの継承メンバーのアクセシビリティを定義します。
目次構文
1)
アクセス指定子の後に宣言されたメンバーは、publicメンバーアクセスを持ちます。
2)
アクセス指定子の後に宣言されたメンバは、protectedメンバアクセスを持ちます。
3)
アクセス指定子の後に宣言されたメンバーは、privateメンバーアクセスを持ちます。
4)
Public inheritance
: アクセス指定子の後にリストされた
base class
のpublicメンバーとprotectedメンバーは、派生クラスにおいて元のメンバーアクセスを保持します。
5)
Protected inheritance
: アクセス指定子の後にリストされた
base class
のpublicおよびprotectedメンバーは、派生クラスのprotectedメンバーとなります。
6)
Private inheritance
: アクセス指定子の後にリストされた
base class
のpublicおよびprotectedメンバーは、派生クラスのprivateメンバーとなります。
基底クラスのprivateメンバは、public、protected、privateのいずれの継承であっても、常に派生クラスからアクセスできません。 説明すべての class メンバー(静的、非静的、関数、型など)の名前には、関連する「メンバーアクセス」があります。プログラム内でメンバーの名前が使用される際、そのアクセスがチェックされ、アクセス規則を満たさない場合、プログラムはコンパイルされません:
このコードを実行
#include <iostream> class Example { public: // この後のすべての宣言はpublic void add(int x) // メンバー関数「add」はpublicアクセス { n += x; // OK: privateメンバーExample::nはExample::addからアクセス可能 } private: // この後のすべての宣言はprivate int n = 0; // メンバー変数「n」はprivateアクセス }; int main() { Example e; e.add(1); // OK: publicメンバーExample::addはmainからアクセス可能 // e.n = 7; // エラー: privateメンバーExample::nはmainからアクセス不可 } アクセス指定子は、クラスの作成者に対して、クラスの利用者(つまり interface )がアクセスできるクラスメンバーと、クラスの内部使用( implementation )のためのメンバーを決定する能力を与えます。 詳細クラスのすべてのメンバ宣言(クラス外で定義されたものを含む)は、そのクラスがアクセスできるすべての名前にアクセスできます。メンバ関数内のローカルクラスは、そのメンバ関数がアクセスできるすべての名前にアクセスできます。 キーワード protected または private メンバへの追加の関数やクラスへのアクセスを許可するには、フレンドシップ宣言 を使用することができます。 アクセス可能性は、名前の起源に関係なくすべての名前に適用されるため、typedef や using 宣言(継承コンストラクタを除く)によって導入された名前がチェックされ、それが参照する名前はチェックされません。 class A : X
{
class B {}; // B is private in A
public:
typedef B BB; // BB is public
};
void f()
{
A::B y; // error: A::B is private
A::BB x; // OK: A::BB is public
}
メンバアクセスは可視性に影響しません。private および private 継承されたメンバの名前は可視であり、オーバーロード解決で考慮され、アクセス不能な基底クラスへの暗黙の変換も引き続き考慮されます。メンバアクセスチェックは、任意の言語構文が解釈された後の最後のステップです。このルールの意図は、任意の デフォルト関数引数 および テンプレートパラメータ で使用される名前のアクセスチェックは、使用時ではなく宣言時に行われます。 仮想関数 の名前に対するアクセスルールは、メンバ関数が呼び出されるオブジェクトを表す式の型を使用して、呼び出し時点でチェックされます。最終オーバーライダーのアクセスは無視されます。 struct B
{
virtual int f(); // f is public in B
};
class D : public B
{
private:
int f(); // f is private in D
};
void f()
{
D d;
B& b = d;
b.f(); // OK: B::f is public, D::f is invoked even though it's private
d.f(); // error: D::f is private
}
非修飾 名前探索 によれば private である名前でも、修飾名探索を通じてアクセス可能になる場合があります。 class A {};
class B : private A {};
class C : public B
{
A* p; // error: unqualified name lookup finds A as the private base of B
::A* q; // OK: qualified name lookup finds the namespace-level declaration
};
継承グラフ内の複数の経路を通じてアクセス可能な名前は、最もアクセスが許可されている経路のアクセスを持ちます。 class W
{
public:
void f();
};
class A : private virtual W {};
class B : public virtual W {};
class C : public A, public B
{
void f()
{
W::f(); // OK: W is accessible to C through B
}
};
クラス内には任意の数のアクセス指定子を任意の順序で記述できます。
メンバが同じクラス内で再宣言される場合、同じメンバアクセスで行われなければなりません。 struct S
{
class A; // S::A is public
private:
class A {}; // error: cannot change access
};
パブリックメンバーアクセスパブリックメンバはクラスのパブリックインターフェースの一部を形成します(パブリックインターフェースの他の部分は ADL によって見つかる非メンバ関数です)。 クラスのpublicメンバはどこからでもアクセス可能です: class S { public: // n, E, A, B, C, U, f は公開メンバーです int n; enum E {A, B, C}; struct U {}; static void f() {} }; int main() { S::f(); // S::f は main 関数内でアクセス可能です S s; s.n = S::B; // S::n と S::B は main 関数内でアクセス可能です S::U x; // S::U は main 関数内でアクセス可能です } プロテクテッドメンバーアクセスプロテクテッドメンバは、基底クラスから派生クラスへのインターフェースを形成します(これはクラスのパブリックインターフェースとは区別されます)。 クラスのprotectedメンバは以下の場合にのみアクセス可能です
1)
そのクラスのメンバーおよびフレンドに対して;
2)
そのクラスの派生クラスのメンバーおよびフレンドに対して、ただし保護されたメンバーがアクセスされるオブジェクトのクラスがその派生クラスまたはその派生クラスの派生クラスである場合に限る:
struct Base { protected: int i; private: void g(Base& b, struct Derived& d); }; struct Derived : Base { friend void h(Base& b, Derived& d); void f(Base& b, Derived& d) // 派生クラスのメンバー関数 { ++d.i; // OK: dの型はDerived ++i; // OK: 暗黙の'*this'の型はDerived // ++b.i; // エラー: Baseを通じてprotectedメンバーにアクセスできない // (そうでなければ、仮想的なDerived2のような他の派生クラスの // 基底実装を変更することが可能になってしまう) } }; void Base::g(Base& b, Derived& d) // Baseのメンバー関数 { ++i; // OK ++b.i; // OK ++d.i; // OK } void h(Base& b, Derived& d) // Derivedのフレンド関数 { ++d.i; // OK: DerivedのフレンドはDerivedのオブジェクトを通じて // protectedメンバーにアクセス可能 // ++b.i; // エラー: DerivedのフレンドはBaseのフレンドではない } void x(Base& b, Derived& d) // 非メンバー非フレンド関数 { // ++b.i; // エラー: 非メンバーからのアクセス不可 // ++d.i; // エラー: 非メンバーからのアクセス不可 } 保護されたメンバへのポインタが形成される場合、その宣言では派生クラスを使用する必要があります: struct Base { protected: int i; }; struct Derived : Base { void f() { // int Base::* ptr = &Base::i; // エラー: Derivedを使用して指定する必要があります int Base::* ptr = &Derived::i; // OK } }; プライベートメンバーアクセスプライベートメンバは、クラスの実装を形成するとともに、クラスの他のメンバに対するプライベートインターフェースを提供します。 クラスのプライベートメンバーは、そのクラスのメンバーとフレンドのみがアクセス可能であり、メンバーが同じインスタンスまたは異なるインスタンスにあるかどうかに関わらず同様です: class S { private: int n; // S::n は private public: S() : n(10) {} // this->n は S::S 内でアクセス可能 S(const S& other) : n(other.n) {} // other.n は S::S 内でアクセス可能 }; explicit cast (Cスタイルおよび関数スタイル)は、派生lvalueからそのprivate基底への参照へのキャスト、または派生へのポインタからそのprivate基底へのポインタへのキャストを許可します。 継承derived classes におけるpublic、protected、private継承の意味については、こちらを参照してください。 キーワード不具合報告以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||