クラス X のフレンドとは、X のメンバーではないが、X のメンバーと
同じ X へのアクセスを認可されている関数またはクラスです。
クラス・メンバー・リスト内で、friend 指定子を使用して宣言された関数は、
そのクラスのフレンド関数 と呼ばれます。
別のクラスのメンバー・リスト内で friend 指定子を用いて宣言されたクラスは、そのクラスのフレンド・クラス と呼ばれます。
クラス Y を定義してからでなければ、Y の任意のメンバーを、別のクラスのフレンドとして宣言することはできません。
以下の例では、フレンド関数 print は、クラス Y のメンバーであり、 クラス X の private データ・メンバー a および b にアクセスします。
#include <iostream> using namespace std; class X; class Y { public: void print(X& x); }; class X { int a, b; friend void Y::print(X& x); public: X() : a(1), b(2) { } }; void Y::print(X& x) { cout << "a is " << x.a << endl; cout << "b is " << x.b << endl; } int main() { X xobj; Y yobj; yobj.print(xobj); }
次に、上記の例の出力を示します。
a is 1 b is 2
クラス全体をフレンドとして宣言することができます。 クラス F が、クラス A のフレンドであるとします。 メンバー関数、およびクラス F の静的データ・メンバー定義はいずれも、クラス A に アクセスすることができます。
次の例では、フレンド・クラス F には、クラス X の private データ・メンバー a および b にアクセスする、メンバー関数 print があります。 これは、前述の例のフレンド関数 print と同じタスクを実行します。 また、クラス F に宣言されたその他のメンバーも、クラス X のメンバーすべてにアクセスできます。
#include <iostream> using namespace std; class X { int a, b; friend class F; public: X() : a(1), b(2) { } }; class F { public: void print(X& x) { cout << "a is " << x.a << endl; cout << "b is " << x.b << endl; } }; int main() { X xobj; F fobj; fobj.print(xobj); }
次に、上記の例の出力を示します。
a is 1 b is 2
クラスをフレンドとして宣言する場合は、詳述型指定子を使用する必要があります。 次の例は、このことを示しています。
class F; class G; class X { friend class F; friend G; };
コンパイラーは、G のフレンド宣言が、詳述クラス名でなければならないことを警告します。
フレンド宣言では、クラスを定義できません。 例えば、コンパイラーは、次の表記を許可しません。
class F; class X { friend class F { }; };
しかし、フレンド宣言で関数を定義することができます。 クラスは非ローカル・クラス関数になっている必要があり、関数名は非修飾で、関数はネーム・スペース・スコープを 持っている必要があります。 次の例は、このことを示しています。
class A { void g(); }; void z() { class B { // friend void f() { }; }; } class C { // friend void A::g() { } friend void h() { } };
コンパイラーは、f() または g() の関数定義を許可しません。 コンパイラーは、h() の定義は認めます。
ストレージ・クラス指定子を使用して、フレンドを宣言することはできません。
関連参照