メンバー アクセス コントロール (C++)

アクセス制御を使用すると、クラスのパブリック -cpp" data-linktype="relative-path">インターフェイスを private publicpublic -cpp" data-linktype="relative-path">実装の詳細と private protected -cpp" data-linktype="relative-path">protected メンバーから分離できます。これは派生クラスでのみ使用されます。 アクセス指定子は、その後で宣言されたすべてのメンバーに対して当てはまり、これは、次のアクセス指定子が検出されるまで続きます。

class Point
{
public:
    Point( int, int ) // Declare public constructor.;
    Point();// Declare public default constructor.
    int &x( int ); // Declare public accessor.
    int &y( int ); // Declare public accessor.

private:                 // Declare private state variables.
    int _x;
    int _y;

protected:      // Declare protected function for derived classes only.
    Point ToWindowCoords();
};

既定のアクセスは private クラス内で、構造体 public または共用体では です。 クラスのアクセス指定子は、任意の順序で何回でも使用できます。 クラス型のオブジェクトに対するストレージの割り当ては、実装に依存します。 ただし、コンパイラは、アクセス指定子間で連続して高いメモリ アドレスへのメンバーの割り当てを保証する必要があります。

メンバー アクセス コントロール

アクセスの種類 意味
private -cpp" data-linktype="relative-path">private として宣言されたクラス メンバーは、 クラスのメンバー関数 private およびフレンド (クラスまたは関数) でのみ使用できます。
protected -cpp" data-linktype="relative-path">protected として宣言されたクラス メンバー protected は、 クラスのメンバー関数およびフレンド (クラスまたは関数) で使用できます。 また、そのクラスから派生したクラスも "protected" メンバーを使用できます。
public -cpp" data-linktype="relative-path">public として宣言されたクラス メンバー public は、任意の関数で使用できます。

アクセス制御を使用すると、オブジェクトの使用を意図しない方法で使用することを防ぐのに役立ちます。 明示的な型変換 (キャスト) を行った場合、この保護は失われます。

Note

アクセス制御は、すべての名前 (メンバー関数、メンバー データ、入れ子のクラス、列挙子) に同等に適用できます。

派生クラスのアクセス コントロール

派生クラスでアクセスできる基底クラスのメンバーは、次の 2 つの要因によって制御されます。派生クラスの継承メンバーに対するアクセスも、この同じ要因によって制御されます。

  • 派生クラスがアクセス指定子を使用して基本クラスを public 宣言するかどうか。

  • 基底クラスでメンバーへのアクセスがどのように指定されているか。

次の表は、これらの要因間の相互作用と、基底クラスのメンバーへのアクセスがどのように決定されるかを示しています。

基底クラスのメンバー アクセス

private protected public
派生アクセスで常にアクセスできない private 派生クラスで派生を使用 private する場合 private 派生クラスで派生を使用 private する場合
protected 派生クラスで派生を使用 protected する場合 protected 派生クラスで派生を使用 protected する場合
protected 派生クラスで派生を使用 public する場合 public 派生クラスで派生を使用 public する場合

次の例は、アクセスの派生を示しています。

// access_specifiers_for_base_classes.cpp
class BaseClass
{
public:
    int PublicFunc(); // Declare a public member.
protected:
    int ProtectedFunc(); // Declare a protected member.
private:
    int PrivateFunc(); // Declare a private member.
};

// Declare two classes derived from BaseClass.
class DerivedClass1 : public BaseClass
{
    void foo()
    {
        PublicFunc();
        ProtectedFunc();
        PrivateFunc(); // function is inaccessible
    }
};

class DerivedClass2 : private BaseClass
{
    void foo()
    {
        PublicFunc();
        ProtectedFunc();
        PrivateFunc(); // function is inaccessible
    }
};

int main()
{
    DerivedClass1 derived_class1;
    DerivedClass2 derived_class2;
    derived_class1.PublicFunc();
    derived_class2.PublicFunc(); // function is inaccessible
}

では DerivedClass1 、 メンバー関数はメンバーであり、 は基本クラスなので PublicFuncpublicProtectedFuncprotectedBaseClasspublic メンバーです。 PrivateFuncprivateBaseClass 対し、派生クラスにはアクセスできません。

では DerivedClass2 、 が基本クラスなので、 関数と PublicFuncProtectedFuncprivate 関数 BaseClass はメンバーと private 見なされます。 繰り PrivateFunc 返しになりますが、 は であり privateBaseClass 、派生クラスにはアクセスできません。

基底クラスにアクセス指定子を使用しなくても、派生クラスを宣言できます。 このような場合、派生クラス宣言で キーワードが使用されている場合、派生 private が考慮 class されます。 派生クラス宣言で キーワード public が使用されている場合、派生が考慮 struct されます。 コード例を次に示します。

class Derived : Base
...

は以下に匹敵します。

class Derived : private Base
...

同様に、

struct Derived : Base
...

は以下に匹敵します。

struct Derived : public Base
...

アクセス権を持つとして宣言されたメンバーは、それらの関数またはクラスが基本クラスの宣言を使用して宣言されていない限り、関数または派生クラス privatefriend からアクセスできません。

union に基本クラスを設定できない。

Note

基本クラスを指定する場合は、 キーワードを明示的に使用して、派生クラスのユーザーがメンバー アクセス privateprivate を理解する必要があります。

アクセス制御と静的メンバー

として基本クラスを指定すると private 、非静的メンバーにのみ影響します。 パブリックな静的メンバーは、派生クラス内でもアクセスできます。 ただし、ポインター、参照、またはオブジェクトを使用して基本クラスのメンバーにアクセスするには、アクセス制御を再度適用する変換が必要な場合があります。 次の例を考えてみましょう。

// access_control.cpp
class Base
{
public:
    int Print();             // Nonstatic member.
    static int CountOf();    // Static member.
};

// Derived1 declares Base as a private base class.
class Derived1 : private Base
{
};

// Derived2 declares Derived1 as a public base class.
class Derived2 : public Derived1
{
    int ShowCount();    // Nonstatic member.
};

// Define ShowCount function for Derived2.
int Derived2::ShowCount()
{
    // Call static member function CountOf explicitly.
    int cCount = ::Base::CountOf();     // OK.

    // Call static member function CountOf using pointer.
    cCount = this->CountOf();  // C2247: 'Base::CountOf'
                               // not accessible because
                               // 'Derived1' uses 'private'
                               // to inherit from 'Base'
    return cCount;
}

このコードでは、アクセス制御により、Derived2 へのポインターから Base へのポインターへの変換が禁止されます。 ポインター this は暗黙的に 型です Derived2 * 。 関数を選択 CountOf するには、 this を 型に変換する必要があります Base * 。 は への間接的な基本クラスなので Base 、このような private 変換は許可されません Derived2 。 基本クラス型 private への変換は、直接の派生クラスへのポインターに対してだけ受け入れ可能です。 型のポインターを 型に変換 Derived1 * できるのは、その理由です Base *

ポインター、参照、またはオブジェクトを使用せずに関数を明示的に呼び出した場合、その関数を選択する場合、変換 CountOf は意味しません。 呼び出しが許可されているのは、その理由です。

派生クラスのメンバーと友人は、ポインターを の直接の基本クラスへのポインター TTprivate に変換できます T

仮想関数へのアクセス

関数に適用されるアクセス virtual 制御は、関数呼び出しの作成に使用される型によって決まります。 関数の宣言をオーバーライドした場合、特定の型のアクセス制御には影響しません。 例:

// access_to_virtual_functions.cpp
class VFuncBase
{
public:
    virtual int GetState() { return _state; }
protected:
    int _state;
};

class VFuncDerived : public VFuncBase
{
private:
    int GetState() { return _state; }
};

int main()
{
   VFuncDerived vfd;             // Object of derived type.
   VFuncBase *pvfb = &vfd;       // Pointer to base type.
   VFuncDerived *pvfd = &vfd;    // Pointer to derived type.
   int State;

   State = pvfb->GetState();     // GetState is public.
   State = pvfd->GetState();     // C2248 error expected; GetState is private;
}

前の例では、 型へのポインターを使用して仮想関数を呼び出し、 を呼び出し GetStateVFuncBaseVFuncDerived::GetStateGetState として扱います public 。 ただし、 型へのポインターを使用して を呼び出すのは、クラス で が宣言されたため、 GetStateVFuncDerivedGetState アクセス制御 private 違反です VFuncDerived

注意事項

仮想関数 GetState は、基底クラス VFuncBase へのポインターを使用して呼び出すことができます。 これは、 という関数が、その関数の基本クラス バージョンであるという意味ではありません。

多重継承でのアクセス制御

仮想基底クラスを含む多重継承のグリッドでは、任意の名前に複数のパスを通じてアクセスできます。 パスが異なると適用できるアクセス制御も異なるため、コンパイラは最大のアクセスを許可するパスを選択します。 次の図を参照してください。

Diagram showing access along the paths of an inheritance graph.
継承グラフのパスに沿ったアクセス

図では、クラス VBase で宣言される名前は、必ずクラス RightPath 経由でアクセスされます。 は基本クラスとして宣言し、 は として宣言されるので、適切 RightPathVBase なパス publicLeftPath にアクセス VBase しやすくなっています private

関連項目

C++ 言語リファレンス