フレンド


関数からの非公開領域アクセス

非公開メンバへのアクセスは、通常は同一クラス内関数のみです
しかし、関数から非公開メンバへのアクセスができると便利なこともあります

C++では、関数のなかでも特別なフレンド関数というものが存在します
フレンド関数は、メンバ関数ではないが非公開メンバと被保護メンバへアクセスできます

フレンド関数を定義するには、まずクラスのメンバ宣言部に
friendキーワードを付加した関数のプロトタイプを宣言します
これに、この関数を通常の関数として定義します
class {
	friend type function(arg-list);
};

type function(arg-list) {
	statements..
}
typeは戻り値、arg-listは引数リストを指定します
これで、関数 function() はクラスの非公開メンバへアクセスすることができます
フレンド関数のプロトタイプの宣言位置のアクセス領域は問われません
#include<iostream>
using namespace std;

class Kitty {
	char *str;
	friend char * getStr(Kitty &);
public:
	Kitty(char *str) { Kitty::str = str; }
} obj("Kitty on your lap") ;

char * getStr(Kitty & obj) {
	return obj.str;
}

int main() {
	cout << getStr(obj);
	return 0;
}
getStr() 関数は、Kittyクラスのフレンド関数です
そのため、この関数からはKittyクラスのプライベートメンバにアクセスできます
ただし、オブジェクトを持たないため引数でオブジェクトを受け取っていますね
これはフレンド関数ではよく使われる動作です

フレンド関数はメンバ関数ではないということを忘れないでください
上のプログラムで obj.getStr() という表現は間違っています
フレンド関数の呼び出しは、通常の関数として扱います
さらに、フレンド関数は this ポインタもなく、継承もされません

また、フレンド関数は複数のクラスで宣言することができます
#include<iostream>
using namespace std;

class Age;

class Name {
	char *name;
public:
	friend void print(Name & , Age &);
	Name(char *name) { Name::name = name; }
} n_obj("Rena") ;

class Age {
	int age;
public:
	friend void print(Name & , Age &);
	Age(int age) { Age::age = age; }
} a_obj(15) ;

void print(Name &n , Age &a) {
	cout << "名前 : " << n.name << "\t年齢 : " << a.age << '\n';
}

int main() {
	print(n_obj , a_obj);
	return 0;
}
フレンド関数 print() は、Name クラスと Age クラスの両方で宣言されています
print() 関数は、この両方のクラスの非公開メンバへアクセスできます


フレンドクラス

フレンド関数に続き、フレンドクラスというものも存在します
予想どおりフレンドクラスからは、そのクラスの非公開メンバへ自由にアクセスできます
フレンドクラスは、全メンバ関数が特定のクラスのフレンド関数であるクラスなのです

フレンドクラスの指定も、フレンド関数同様に friend キーワードで行います
次の構文を参照してください

friend class-name;

class-name はフレンドクラスとするクラス名を指定します
ここで指定したクラスのメンバからは、これを宣言したクラスの非公開メンバへアクセスできます
#include<iostream>
using namespace std;

class Neko;

class Kitty {
	char *str;
public:
	friend Neko;
	Kitty(char *str) { Kitty::str = str; }
} obj("Kitty on your lap");

class Neko {
public:
	Neko(Kitty &obj) {
		cout << obj.str << '\n';
	}
};

int main() {
	Neko obj(::obj);
	return 0;
}
Neko クラスは、Kitty クラスのフレンドクラスです
Neko クラスのメンバからは、自由に Kitty クラスの非公開メンバへアクセスできます


friend

friend class-name;
friend function-declarator;

関数またはクラスから、別のクラスのprivateメンバ
または、protectedメンバへアクセスすることができます

class-name : フレンドになるクラス名を指定します
function-declarator : フレンドになる関数のプロトタイプを指定します



前のページへ戻る次のページへ