7.1 友元函數(shù)
C++只有本類中的函數(shù)可以訪問(wèn)本類的 private 成員。
但一種情況例外,那就是友元(friend)。友元可以使得其他類中的成員函數(shù)以及全局范圍內(nèi)的函數(shù)訪問(wèn)當(dāng)前類的 private 成員。
在當(dāng)前類以外定義的,不屬于當(dāng)前類的函數(shù)也可以在當(dāng)前類中聲明,但要在前面加 friend 關(guān)鍵字,這樣的函數(shù)就是友元函數(shù)。
注意:友元函數(shù)可以是不屬于任何類的非成員函數(shù),也可以是其他類的成員函數(shù)。
友元函數(shù)可以訪問(wèn)當(dāng)前類中的所有成員(包括 public、protected、private修飾的成員)。
1、將非成員函數(shù)聲明為友元函數(shù)。
#include <iostream>
using namespace std;
class Student{
public:
Student(char *name, int age, float score);
public:
friend void show(Student *pstu); //將show()聲明為友元函數(shù)
private:
char *name;
int age;
float score;
};
Student::Student(char *name, int age, float score): name(name), age(age), score(score){ }
//非成員函數(shù)
void show(Student *ps){
cout<<ps->name<<"的年齡是 "<<ps->age<<",成績(jī)是 "<<ps->score<<endl;
}
int main(){
Student stu("豆豆", 18, 80.0);
show(&stu); //調(diào)用友元函數(shù)
Student *ps = new Student("呵呵", 17, 90.0);
show(ps); //調(diào)用友元函數(shù)
return 0;
}

注意:在友元函數(shù)中不能直接訪問(wèn)類的成員,必須要借助對(duì)象。
類的成員函數(shù)可以通過(guò)this指針完成屬性的調(diào)用,但是友元函數(shù)無(wú)法使用this,所以在該函數(shù)內(nèi)部需要為其傳遞一個(gè)對(duì)象的參數(shù),用來(lái)調(diào)用屬性,形參可以直接傳遞對(duì)象,也可以傳遞對(duì)象指針或?qū)ο笠谩?/p>
7.2 將其他類的成員函數(shù)聲明為友元函數(shù)
友元函數(shù)不僅可以是全局函數(shù)(非成員函數(shù)),還可以是另外一個(gè)類的成員函數(shù)。
#include <iostream>
using namespace std;
class Address; //提前聲明Address類
//聲明Student類
class Student{
public:
Student(char *name, int age, float score);
public:
void show(Address *addr);
private:
char *name;
int age;
float score;
};
//聲明Address類
class Address{
private:
char *province; //省份
char *city; //城市
char *district; //區(qū)(市區(qū))
public:
Address(char *province, char *city, char *district);
//將Student類中的成員函數(shù)show()聲明為友元函數(shù)
friend void Student::show(Address *addr);
};
//實(shí)現(xiàn)Student類
Student::Student(char *name, int age, float score): name(name), age(age), score(score){ }
void Student::show(Address *addr){
cout<<name<<"的年齡是 "<<age<<",成績(jī)是 "<<score<<endl;
cout<<"家庭住址:"<<addr->province<<"省"<<addr->city<<"市"<<addr->district<<"區(qū)"<<endl;
}
//實(shí)現(xiàn)Address類
Address::Address(char *province, char *city, char *district){
this->province = province;
this->city = city;
this->district = district;
}
int main(){
Student stu("豆豆", 18, 80.0);
Address addr("遼寧", "沈陽(yáng)", "渾南");
stu.show(&addr);
Student *ps = new Student("呵呵", 17, 90.0);
Address *paddr = new Address("遼寧", "大連", "甘井子");
ps->show(paddr);
return 0;
}

注意:一個(gè)函數(shù)可以被多個(gè)類聲明為友元函數(shù),這樣就可以訪問(wèn)多個(gè)類中的 private 成員。
7.3 友元類
我們呢還可以將整個(gè)類聲明為另一個(gè)類的友元類,這樣友元類中的所有成員函數(shù)都是另外一個(gè)類的友元函數(shù)。
例如將類 B 聲明為類 A 的友元類,那么類 B 中的所有成員函數(shù)都是類 A 的友元函數(shù),可以訪問(wèn)類 A 的所有成員,包括 public、protected、private 屬性的。
將Student類聲明為Address類的友元類,在Address類中
public:
//將Student類聲明為Address類的友元類
friend class Student;
注意:
1、友元的關(guān)系是單向的。
類 B 是類 A 的友元類,不等于類 A 是類 B 的友元類。
2、友元的關(guān)系不能傳遞。類 A 是類 B 的友元類,類 B 是類 C 的友元類,但類 A不是類 C 的友元類(朋友的朋友不一定也是朋友)。
3、為了數(shù)據(jù)的安全性,一般我們只聲明友元函數(shù),友元類極少使用。