friend (C++)friend (C++)

状況によっては、クラスのメンバーではない関数、または別のクラスのすべてのメンバーにメンバー レベルのアクセスを許可する方が便利です。In some circumstances, it is more convenient to grant member-level access to functions that are not members of a class or to all members in a separate class. クラスの実装側が自分のフレンドを宣言することだけが可能です。Only the class implementer can declare who its friends are. 関数またはクラスが自分自身をいずれかのクラスのフレンドとして宣言することはできません。A function or class cannot declare itself as a friend of any class. クラスの定義で使用して、フレンドキーワードと、非メンバー関数またはクラスのプライベートおよびプロテクト メンバーにアクセス権を付与するには、その他のクラスの名前。In a class definition, use the friend keyword and the name of a non-member function or other class to grant it access to the private and protected members of your class. テンプレートの定義で型パラメーターは、フレンドとして宣言できます。In a template definition, a type parameter can be declared as a friend.

構文Syntax

class friend F
friend F;

フレンド宣言Friend declarations

以前に宣言されなかったフレンド関数を宣言すると、その関数は外側の非クラス スコープにエクスポートされます。If you declare a friend function that was not previously declared, that function is exported to the enclosing nonclass scope.

フレンド宣言で宣言された関数として扱われますを使用して宣言された、 externキーワード。Functions declared in a friend declaration are treated as if they had been declared using the extern keyword. 詳細については、次を参照してください。 externします。For more information, see extern.

グローバル スコープの関数はプロトタイプの前にフレンドとして宣言できますが、メンバー関数は、完全なクラス宣言の前にフレンドとして宣言することはできません。Although functions with global scope can be declared as friends prior to their prototypes, member functions cannot be declared as friends before the appearance of their complete class declaration. 次のコードは、なぜこれが失敗するかを示します。The following code shows why this fails:

class ForwardDeclared;   // Class name is known.
class HasFriends
{
    friend int ForwardDeclared::IsAFriend();   // C2039 error expected
};

前の例では、スコープにクラス名 ForwardDeclared を入力しますが、宣言全体、特に関数 IsAFriend を宣言する部分は不明です。The preceding example enters the class name ForwardDeclared into scope, but the complete declaration — specifically, the portion that declares the function IsAFriend — is not known. そのため、フレンドクラスの宣言でHasFriendsエラーが生成されます。Therefore, the friend declaration in class HasFriends generates an error.

クラスのフレンド宣言の 2 つの形式がある、c++ 11 以降します。Starting in C++11, there are two forms of friend declarations for a class:

friend class F;
friend F;

最初のフォームでは、最も内側の名前空間にその名前の既存のクラスが見つからなかった場合、新しいクラス F が導入されています。The first form introduces a new class F if no existing class by that name was found in the innermost namespace. C++ 11:2 番目の形式は、新しいクラスを導入していませんクラスは既に宣言されているし、テンプレートの型パラメーターまたはフレンドとしての typedef を宣言するときに使用する必要がありますが使用できます。C++11: The second form does not introduce a new class; it can be used when the class has already been declared, and it must be used when declaring a template type parameter or a typedef as a friend.

使用class friend Fと参照先の型はまだ宣言されていません。Use class friend F when the referenced type has not yet been declared:

namespace NS
{
    class M
    {
        class friend F;  // Introduces F but doesn't define it
    };
}
namespace NS
{
    class M
    {
        friend F; // error C2433: 'NS::F': 'friend' not permitted on data declarations
    };
}

次の例では、friend Fを指す、 F NS のスコープ外部で宣言されたクラスです。In the following example, friend F refers to the F class that is declared outside the scope of NS.

class F {};
namespace NS
{
    class M
    {
        friend F;  // OK
    };
}

使用friend Fフレンドとしてテンプレート パラメーターを宣言します。Use friend F to declare a template parameter as a friend:

template <typename T>
class my_class
{
    friend T;
    //...
};

使用friend Fフレンドとしての typedef を宣言します。Use friend F to declare a typedef as friend:

class Foo {};
typedef Foo F;

class G
{
    friend F; // OK
    friend class F // Error C2371 -- redefinition
};

相互にフレンドである 2 つのクラスを宣言するには、2 番目のクラス全体が最初のクラスのフレンドとして指定される必要があります。To declare two classes that are friends of one another, the entire second class must be specified as a friend of the first class. この制限の理由は、2 番目のクラスが宣言された位置でのみコンパイラは個々のフレンド関数を宣言するために十分な情報を得られるためです。The reason for this restriction is that the compiler has enough information to declare individual friend functions only at the point where the second class is declared.

注意

2 番目のクラス全体は最初のクラスへのフレンドである必要がありますが、最初のクラスのどの関数が 2 番目のクラスのフレンドであるかを選択できます。Although the entire second class must be a friend to the first class, you can select which functions in the first class will be friends of the second class.

friend 関数friend functions

Aフレンド関数は、クラスのメンバーではないが、クラスのプライベートおよびプロテクト メンバーにアクセスする関数。A friend function is a function that is not a member of a class but has access to the class's private and protected members. friend 関数はクラス メンバーと見なされません。これらの関数は、特別なアクセス特権が付与されている標準の外部関数です。Friend functions are not considered class members; they are normal external functions that are given special access privileges. Friend はクラスのスコープでないと、メンバー選択演算子を使用して呼び出されません (します。Friends are not in the class's scope, and they are not called using the member-selection operators (. および > ) 別のクラスのメンバーでない限りです。and ->) unless they are members of another class. Aフレンド関数がアクセスを許可しているクラスで宣言されています。A friend function is declared by the class that is granting access. フレンドクラス宣言で宣言をどこにでも配置できます。The friend declaration can be placed anywhere in the class declaration. アクセス制御キーワードによる影響はありません。It is not affected by the access control keywords.

次に、Point クラスと ChangePrivate フレンド関数の例を示します。The following example shows a Point class and a friend function, ChangePrivate. フレンド関数のプライベート データ メンバーへのアクセスには、Pointをパラメーターとして受け取るオブジェクトします。The friend function has access to the private data member of the Point object it receives as a parameter.

// friend_functions.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
class Point
{
    friend void ChangePrivate( Point & );
public:
    Point( void ) : m_i(0) {}
    void PrintPrivate( void ){cout << m_i << endl; }

private:
    int m_i;
};

void ChangePrivate ( Point &i ) { i.m_i++; }

int main()
{
   Point sPoint;
   sPoint.PrintPrivate();
   ChangePrivate(sPoint);
   sPoint.PrintPrivate();
// Output: 0
           1
}

フレンドとしてのクラス メンバーClass members as friends

クラス メンバー関数は他のクラスのフレンドとして宣言できます。Class member functions can be declared as friends in other classes. 次に例を示します。Consider the following example:

// classes_as_friends1.cpp
// compile with: /c
class B;

class A {
public:
   int Func1( B& b );

private:
   int Func2( B& b );
};

class B {
private:
   int _b;

   // A::Func1 is a friend function to class B
   // so A::Func1 has access to all members of B
   friend int A::Func1( B& );
};

int A::Func1( B& b ) { return b._b; }   // OK
int A::Func2( B& b ) { return b._b; }   // C2248

この例では、A::Func1( B& ) 関数に B クラスへのフレンド アクセスのみ許可されます。In the preceding example, only the function A::Func1( B& ) is granted friend access to class B. そのため、プライベート メンバーへのアクセスを_bで正しいFunc1クラスのAではなくFunc2します。Therefore, access to the private member _b is correct in Func1 of class A but not in Func2.

friend クラスは、すべてのメンバー関数が、クラスのその他のプライベート メンバーとプロテクト メンバーにアクセスできるメンバー関数を持つ、クラスのフレンド関数であるクラスです。A friend class is a class all of whose member functions are friend functions of a class, that is, whose member functions have access to the other class's private and protected members. friend クラスの B 宣言が次のようになっていたとします。Suppose the friend declaration in class B had been:

friend class A;

その場合、A クラスのすべてのメンバー関数に B クラスへのフレンド アクセスが許可されます。In that case, all member functions in class A would have been granted friend access to class B. 次に、フレンド クラスの例を示します。The following code is an example of a friend class:

// classes_as_friends2.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
class YourClass {
friend class YourOtherClass;  // Declare a friend class
public:
   YourClass() : topSecret(0){}
   void printMember() { cout << topSecret << endl; }
private:
   int topSecret;
};

class YourOtherClass {
public:
   void change( YourClass& yc, int x ){yc.topSecret = x;}
};

int main() {
   YourClass yc1;
   YourOtherClass yoc1;
   yc1.printMember();
   yoc1.change( yc1, 5 );
   yc1.printMember();
}

明示的に指定されていない限り、フレンド関係は相互関係ではありません。Friendship is not mutual unless explicitly specified as such. 上の例では、YourClass のメンバー関数は YourOtherClass のプライベート メンバーにアクセスできません。In the above example, member functions of YourClass cannot access the private members of YourOtherClass.

マネージ型 (でC++/CLI) 任意のフレンド関数、フレンド クラス、またはフレンド インターフェイスを持つことはできません。A managed type (in C++/CLI) cannot have any friend functions, friend classes, or friend interfaces.

フレンド関係は継承されません。つまり、YourOtherClass から派生したクラスは YourClass のプライベート メンバーにアクセスできません。Friendship is not inherited, meaning that classes derived from YourOtherClass cannot access YourClass's private members. フレンド関係は推移的ではないため、YourOtherClass のフレンドであるクラスは YourClass にアクセスできません。Friendship is not transitive, so classes that are friends of YourOtherClass cannot access YourClass's private members.

次の図は、4 つのクラス宣言 (BaseDerivedaFriendanotherFriend) を示しています。The following figure shows four class declarations: Base, Derived, aFriend, and anotherFriend. aFriend のプライベート メンバー (および Base が継承した可能性があるすべてのメンバー) に直接アクセスできるのは、Base クラスだけです。Only class aFriend has direct access to the private members of Base (and to any members Base might have inherited).

フレンド関係の包含Implications of friend relationship
フレンド関係の包含Implications of friend relationship

インラインのフレンドの定義Inline friend definitions

フレンド関数は、クラス宣言内で (特定の関数本体) 定義できます。Friend functions can be defined (given a function body) inside class declarations. これらの関数はインライン関数であり、メンバーのインライン関数のように、すべてのクラス メンバーが発生した直後、クラス スコープが閉じる前に定義されているように動作します (クラス宣言の末尾)。These functions are inline functions, and like member inline functions they behave as though they were defined immediately after all class members have been seen but before the class scope is closed (the end of the class declaration). クラス宣言内で定義されているフレンド関数は、外側のクラスのスコープになります。Friend functions that are defined inside class declarations are in the scope of the enclosing class.

関連項目See also

キーワードKeywords