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

アクセス制御を分離することを有効にする、パブリックからクラスのインターフェイス、プライベート実装の詳細と保護のみであるメンバーを使用して派生クラス。Access controls enable you to separate the public interface of a class from the private implementation details and the protected members that are only for use by derived classes. アクセス指定子は、その後で宣言されたすべてのメンバーに対して当てはまり、これは、次のアクセス指定子が検出されるまで続きます。The access specifier applies to all members declared after it until the next access specifier is encountered.

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構造体または共用体の。The default access is private in a class, and public in a struct or union. クラスのアクセス指定子は、任意の順序で何回でも使用できます。Access specifiers in a class can be used any number of times in any order. クラス型のオブジェクトに対するストレージの割り当ては実装に依存しますが、メンバーはアクセス指定子の間で順次上位メモリ アドレスが割り当てられることが保証されます。The allocation of storage for objects of class types is implementation dependent, but members are guaranteed to be assigned successively higher memory addresses between access specifiers.

メンバー アクセス コントロールMember-Access Control

アクセスの種類Type of Access 説明Meaning
privateprivate として宣言されたクラス メンバーprivateメンバー関数およびクラスのフレンド (クラスまたは関数) でのみ使用できます。Class members declared as private can be used only by member functions and friends (classes or functions) of the class.
protectedprotected として宣言されたクラス メンバーprotectedメンバー関数およびクラスのフレンド (クラスまたは関数) で使用できます。Class members declared as protected can be used by member functions and friends (classes or functions) of the class. また、そのクラスから派生したクラスも "protected" メンバーを使用できます。Additionally, they can be used by classes derived from the class.
publicpublic として宣言されたクラス メンバーpublic任意の関数で使用できます。Class members declared as public can be used by any function.

アクセス制御により、不適切な方法でオブジェクトを使用するのを防ぐことができます。Access control helps prevent you from using objects in ways they were not intended to be used. 明示的な型変換 (キャスト) を実行すると、この保護機能が働かなくなります。This protection is lost when explicit type conversions (casts) are performed.

注意

アクセス制御は、すべての名前 (メンバー関数、メンバー データ、入れ子のクラス、列挙子) に同等に適用できます。Access control is equally applicable to all names: member functions, member data, nested classes, and enumerators.

派生クラスのアクセス コントロールAccess Control in Derived Classes

派生クラスでアクセスできる基底クラスのメンバーは、次の 2 つの要因によって制御されます。派生クラスの継承メンバーに対するアクセスも、この同じ要因によって制御されます。Two factors control which members of a base class are accessible in a derived class; these same factors control access to the inherited members in the derived class:

  • 派生クラスが基底クラスを使用して、宣言するかどうか、publicアクセス指定子です。Whether the derived class declares the base class using the public access specifier.

  • 基底クラスでメンバーへのアクセスがどのように指定されているか。What the access to the member is in the base class.

次の表は、これらの要因間の相互作用と、基底クラスのメンバーへのアクセスがどのように決定されるかを示しています。The following table shows the interaction between these factors and how to determine base-class member access.

基底クラスのメンバー アクセスMember Access in Base Class

privateprivate protectedprotected PublicPublic
派生のアクセスに関係なく常にアクセスできないAlways inaccessible regardless of derivation access プライベート派生を使用する場合は派生クラス内でプライベートPrivate in derived class if you use private derivation プライベート派生を使用する場合は派生クラス内でプライベートPrivate in derived class if you use private derivation
プロテクト派生を使用する場合は派生クラス内でプロテクトProtected in derived class if you use protected derivation プロテクト派生を使用する場合は派生クラス内でプロテクトProtected in derived class if you use protected derivation
パブリック派生を使用する場合は派生クラス内でプロテクトProtected in derived class if you use public derivation パブリック派生を使用する場合は派生クラス内でパブリックPublic in derived class if you use public derivation

次に例を示します。The following example illustrates this:

// 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 では、メンバー関数 PublicFunc はパブリック メンバーであり、ProtectedFunc がパブリック基底クラスであるため、BaseClass はプロテクト メンバーになります。In DerivedClass1, the member function PublicFunc is a public member and ProtectedFunc is a protected member because BaseClass is a public base class. PrivateFuncBaseClass に対してプライベートであるため、派生クラスからはアクセスできません。PrivateFunc is private to BaseClass, and it is inaccessible to any derived classes.

DerivedClass2 では、PublicFunc がプライベート基底クラスであるため、ProtectedFunc 関数と BaseClass 関数は、プライベート メンバーと見なされます。In DerivedClass2, the functions PublicFunc and ProtectedFunc are considered private members because BaseClass is a private base class. ここでも、PrivateFuncBaseClass に対してプライベートであるため、派生クラスからはアクセスできません。Again, PrivateFunc is private to BaseClass, and it is inaccessible to any derived classes.

基底クラスにアクセス指定子を使用しなくても、派生クラスを宣言できます。You can declare a derived class without a base-class access specifier. このような場合は、派生はプライベートと見なされます、派生クラスの宣言で使用する場合、classキーワード。In such a case, the derivation is considered private if the derived class declaration uses the class keyword. 派生は派生クラスの宣言で使用する場合は、パブリックと見なされます、structキーワード。The derivation is considered public if the derived class declaration uses the struct keyword. コード例を次に示します。For example, the following code:

class Derived : Base
...

上の式は、下の式と同等です。is equivalent to:

class Derived : private Base
...

同様に、Similarly, the following code:

struct Derived : Base
...

上の式は、下の式と同等です。is equivalent to:

struct Derived : public Base
...

プライベート アクセスを持つものとして宣言されたメンバーは関数にアクセスできないことに注意してください。 または、これらの関数またはクラスはを使用して宣言しない限り、派生クラス、friend、基底クラスで宣言します。Note that members declared as having private access are not accessible to functions or derived classes unless those functions or classes are declared using the friend declaration in the base class.

Aunion型が基本クラスを含めることはできません。A union type cannot have a base class.

注意

プライベート基底クラスを指定する場合は、明示的に使用することをお勧め、privateキーワード、派生クラスのユーザーには、メンバー アクセスが理解できるようにします。When specifying a private base class, it is advisable to explicitly use the private keyword so users of the derived class understand the member access.

アクセス制御と静的メンバーAccess control and static members

基本クラスとしてを指定するとprivate、非静的メンバーだけに影響を与えます。When you specify a base class as private, it affects only nonstatic members. パブリックな静的メンバーは、派生クラス内でもアクセスできます。Public static members are still accessible in the derived classes. ただし、ポインター、参照、またはオブジェクトを使用して基底クラスのメンバーにアクセスするには、アクセス制御が再び適用される時点で変換が必要になる場合があります。However, accessing members of the base class using pointers, references, or objects can require a conversion, at which time access control is again applied. 次に例を示します。Consider the following example:

// 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. Conversion of
                               //  Derived2 * to Base * not
                               //  permitted.
    return cCount;
}

このコードでは、アクセス制御により、Derived2 へのポインターから Base へのポインターへの変換が禁止されます。In the preceding code, access control prohibits conversion from a pointer to Derived2 to a pointer to Base. thisポインターは暗黙的に型Derived2 *します。The this pointer is implicitly of type Derived2 *. 選択する、CountOf関数、this型に変換する必要がありますBase *します。To select the CountOf function, this must be converted to type Base *. BaseDerived2 に対するプライベート間接基底クラスであるため、このような変換は許可されません。Such a conversion is not permitted because Base is a private indirect base class to Derived2. プライベート基底クラス型への変換は、直接の派生クラスへのポインターにのみ使用できます。Conversion to a private base class type is acceptable only for pointers to immediate derived classes. したがって、型 Derived1 * のポインターは型 Base * に変換できます。Therefore, pointers of type Derived1 * can be converted to type Base *.

ポインター、参照、またはオブジェクトを使用して選択することなく CountOf 関数を明示的に呼び出すことは、変換を意味しないことに注意してください。Note that calling the CountOf function explicitly, without using a pointer, reference, or object to select it, implies no conversion. したがって、呼び出しは許可されます。Therefore, the call is allowed.

派生クラス T のメンバーとフレンドは T へのポインターを、T のプライベート直接基底クラスへのポインターに変換できます。Members and friends of a derived class, T, can convert a pointer to T to a pointer to a private direct base class of T.

仮想関数へのアクセスAccess to virtual functions

適用されるアクセス制御仮想関数は、関数の呼び出しに使用される型によって決定されます。The access control applied to virtual functions is determined by the type used to make the function call. 関数の宣言のオーバーライドは、特定の型のアクセス制御には影響しません。Overriding declarations of the function do not affect the access control for a given type. 例えば:For example:

// 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;
}

前の例では、型 GetState へのポインターを使用する仮想関数 VFuncBase の呼び出しは、VFuncDerived::GetState を呼び出します。GetState は public として扱われます。In the preceding example, calling the virtual function GetState using a pointer to type VFuncBase calls VFuncDerived::GetState, and GetState is treated as public. ただし、GetStateVFuncDerived クラスで private として宣言されているため、GetState 型へのポインターを使用して VFuncDerived を呼び出すとアクセス制御違反になります。However, calling GetState using a pointer to type VFuncDerived is an access-control violation because GetState is declared private in class VFuncDerived.

注意事項

仮想関数 GetState は、基底クラス VFuncBase へのポインターを使用して呼び出すことができます。The virtual function GetState can be called using a pointer to the base class VFuncBase. これは、呼び出された関数がその関数の基底クラス版であることを意味しません。This does not mean that the function called is the base-class version of that function.

多重継承でのアクセス制御Access control with multiple inheritance

仮想基底クラスを含む多重継承のグリッドでは、任意の名前に複数のパスを通じてアクセスできます。In multiple-inheritance lattices involving virtual base classes, a given name can be reached through more than one path. パスが異なると適用できるアクセス制御も異なるため、コンパイラは最大のアクセスを許可するパスを選択します。Because different access control can be applied along these different paths, the compiler chooses the path that gives the most access. 次の図を参照してください。See the following figure.

継承グラフのパスに沿ったアクセスAccess along paths of an inheritance graph
継承グラフのパスに沿ったアクセスAccess along paths of an inheritance graph

図では、クラス VBase で宣言される名前は、必ずクラス RightPath 経由でアクセスされます。In the figure, a name declared in class VBase is always reached through class RightPath. RightPathVBase をプライベート基底クラスとして宣言するのに対し、LeftPathVBase をパブリック基底クラスとして宣言するため、右のパスの方がアクセスが簡単です。The right path is more accessible because RightPath declares VBase as a public base class, whereas LeftPath declares VBase as private.

関連項目See also

C++ 言語リファレンスC++ Language Reference