C++:友元(非成员友元函数、成员友元函数、友元类)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??3.8 ?友元:友元函數(shù)和友元類?
?友元函數(shù) :既可以是不屬于任何類的非成員函數(shù),也可以是另一個(gè)類的成員函數(shù),統(tǒng)稱為友元函數(shù)。友元函數(shù)不是當(dāng)前類的成員函數(shù),而是獨(dú)立于類的外部函數(shù),但它可以訪問該類所有的成員,包括私有成員、保護(hù)成員和公有成員。在類中聲明友元函數(shù)時(shí),需在其函數(shù)名前加上關(guān)鍵字friend,此聲明可以放在公有部分、也可以放在保護(hù)和私有部分。友元函數(shù)可以定義在類部,也可以定義在類的外部。
3.8.1 將非成員函數(shù)聲明為友元函數(shù)
//1、將非成員函數(shù)聲明為友元函數(shù) // 例3.33 友元函數(shù)的使用 #include<iostream> using namespace std; class Gril{public:Gril(char* n,int a){name = new char[strlen(n)+1];strcpy(name,n);age = a;}~Gril(){delete []name;}friend void display(Gril &);//聲明友元函數(shù) //friend void display(Gril );private:char* name;int age; }; void display(Gril &x) //形參是對(duì)象的引用 //void display(Gril x) //形參是對(duì)象 {cout<<"女孩的姓名是:"<<x.name<<","<<"年齡:"<<x.age<<endl; } int main() {Gril g("小麗",20);display(g); //調(diào)用友元函數(shù),實(shí)參是對(duì)象的引用 return 0; }/*說明:1、友元函數(shù)雖然可以訪問類對(duì)象的私有成員,但它畢竟不是成員函數(shù),因此,在類的外部定義友元函數(shù)時(shí),不必像成員函數(shù)那樣,在函數(shù)名前加 "類名::"2、因?yàn)橛言瘮?shù)不是類的成員,所以它不能直接訪問對(duì)象的數(shù)據(jù)成員,也不能通過this指針訪問對(duì)象的數(shù)據(jù)成員,它必須通過作為入口參數(shù)傳遞進(jìn)來的對(duì)象名(或?qū)ο笾羔槨?duì)象引用)來訪問引用對(duì)象的數(shù)據(jù)成員。3、由于函數(shù)display是Gril類的友元函數(shù),所以display函數(shù)可以訪問Gril中私有數(shù)據(jù)成員 name、age。但是,在它們之前必須加上 "對(duì)象名." */例1:非成員友元函數(shù)
/* 需求:例如有兩個(gè)類Gril和Boy,現(xiàn)要求打印所有的男生和女生的名字和年齡,我們只需一個(gè) 獨(dú)立的函數(shù)print就能完成,但它必須同時(shí)定義為這兩個(gè)類的友元函數(shù)。 */ //例如3.34 一個(gè)函數(shù)定義同時(shí)定義為兩個(gè)類的友元函數(shù) #include<iostream> using namespace std; class Boy; //對(duì)Boy類的提前引用聲明 class Gril{public:Gril(char N[],int A){strcpy(name,N);age = A;}friend void print(Gril &x) //聲明print函數(shù)是Gril類的友元函數(shù) {cout<<"女孩的姓名是:"<<x.name<<" "<<"年齡:"<<x.age<<endl;}private:char name[20];int age; }; class Boy{ //聲明Boy類 public:Boy(char N[],int A){strcpy(name,N);age = A;}friend void print(Boy &y) //聲明print函數(shù)是Boy類的友元函數(shù) {cout<<"男孩的姓名是:"<<y.name<<" "<<"年齡:"<<y.age<<endl;}private:char name[20];int age; }; int main() {Gril g1("王萌",12); //定義Gril類對(duì)象g1 Gril g2("李芳",14); //定義Gril類對(duì)象g2Gril g3("張麗",18); //定義Gril類對(duì)象g3 Boy b1("張三",11); //定義Boy類對(duì)象b1Boy b2("李四",19); //定義Boy類對(duì)象b2Boy b3("王武",13); //定義Boy類對(duì)象b3 print(g1); //調(diào)用友元函數(shù),實(shí)參是Gril對(duì)象g1 print(g2); //調(diào)用友元函數(shù),實(shí)參是Gril對(duì)象g2print(g3); //調(diào)用友元函數(shù),實(shí)參是Gril對(duì)象g3 print(b1); //調(diào)用友元函數(shù),實(shí)參是Boy對(duì)象b1print(b2); //調(diào)用友元函數(shù),實(shí)參是Boy對(duì)象b2print(b3); //調(diào)用友元函數(shù),實(shí)參是Boy對(duì)象b3return 0; }例2:非成員友元函數(shù)
#include<iostream> using namespace std; class Boy; //對(duì)Boy類的提前引用聲明 class Gril{public:Gril(char N[],int A){strcpy(name,N);age = A;}friend void print(Gril &,Boy &); //聲明print函數(shù)是Gril類的友元函數(shù) private:char name[20];int age; }; class Boy{ //聲明Boy類 public:Boy(char N[],int A){strcpy(name,N);age = A;}friend void print(Gril &,Boy &); //聲明print函數(shù)是Boy類的友元函數(shù)private:char name[20];int age; }; void print(Gril &x,Boy &y) //定義print有元函數(shù) {cout<<"女孩的姓名是:"<<x.name<<" "<<"年齡:"<<x.age<<endl;cout<<"男孩的姓名是:"<<y.name<<" "<<"年齡:"<<y.age<<endl; } int main() {Gril g1("王萌",12); //定義Gril類對(duì)象g1 Gril g2("李芳",14); //定義Gril類對(duì)象g2Gril g3("張麗",18); //定義Gril類對(duì)象g3 Boy b1("張三",11); //定義Boy類對(duì)象b1Boy b2("李四",19); //定義Boy類對(duì)象b2Boy b3("王武",13); //定義Boy類對(duì)象b3 print(g1,b1); //調(diào)用友元函數(shù),實(shí)參是Gril對(duì)象g1,Boy對(duì)象b1print(g2,b2); //調(diào)用友元函數(shù),實(shí)參是Gril對(duì)象g2,Boy對(duì)象b2print(g3,b3); //調(diào)用友元函數(shù),實(shí)參是Gril對(duì)象g3,Boy對(duì)象b3return 0; }3.8.2將成員函數(shù)聲明為友元函數(shù)
除了一般的非成員函數(shù)可以作為某個(gè)類的友元外,一個(gè)類的成員函數(shù)也可以作為另一個(gè)類的友元,它是友元函數(shù)中的一種,成為友元成員函數(shù)。友元成員函數(shù)不僅可以訪問自己所在類對(duì)象中的私有成員和公有成員,還可以訪問friend聲明語(yǔ)句所在類對(duì)象中的所有成員。
例3.35 一個(gè)類的成員函數(shù)作為另一個(gè)類的友元函數(shù)
#include<iostream> #include<string> using namespace std; class Gril; //對(duì)類Gril提前引用聲明 class Boy{public:Boy(char* n,int a){name = new char[strlen(n)+1];strcpy(name,n);age = a;}void disp(Gril ); //聲明函數(shù)dis為類Boy為成員函數(shù) ~Boy(){delete []name;}private:char* name;int age; }; class Gril{public:Gril(char* n,int a){name = new char[strlen(n)+1];strcpy(name,n);age = a;}friend void Boy::disp(Gril ); //聲明類Boy成員函數(shù)dis為類Gril的友元函數(shù) ~Gril(){delete []name;}private:char* name;int age; }; void Boy::disp(Gril x) //定義類Boy的成員函數(shù)disp,同時(shí)也為類Gril的友元函數(shù), { //形參為Gril類對(duì)象 cout<<"男孩的姓名:"<<name<<endl; //函數(shù)disp作為Boy類的成員函數(shù) ,可以訪問Boy類對(duì)象的私有成員 cout<<"男孩的年齡:"<<age<<endl; //注釋同上 cout<<"女孩的姓名:"<<x.name<<endl;//函數(shù)disp作為Gril類的友元函數(shù),可以訪問Gril類對(duì)象的私有成員cout<<"女孩的年齡:"<<x.age<<endl; //注釋同上 } int main() {Boy b("陳大林",11);Gril g("張曉好",12);b.disp(g);//調(diào)用Boy類的對(duì)象b的成員函數(shù)和Gril類的友元函數(shù)disp,實(shí)參是Gril類的對(duì)象g //因?yàn)楹瘮?shù)disp是Boy類的成員函數(shù),所以無需通過傳遞對(duì)象,可以直接訪問自己的私有數(shù)據(jù)成員 return 0; } 3.8.3 友元類
不僅函數(shù)可以作為一個(gè)類的友元,一個(gè)類也可以作為另一個(gè)類的友元,稱為友元類。友元類
的說明方法是在另一個(gè)類聲明中加入語(yǔ)句。
friend class 類名;
此類名是友元類的類名。這條語(yǔ)句可以放在公有部分,也可以放在私有部分。例如,
class Y{
? ? ? ...
};
class X{
? ? ? ...
friend class Y; //聲明類Y是類X的友元類
? ? ? ...
};
當(dāng)類Y被說明類X的友元時(shí),類Y的所有成員函數(shù)都成為類X的友元函數(shù),這就意味著作為
友元類Y中的所有成員函數(shù)都可以訪問類X中的所有成員(包括私有成員)。
下面的例子中,聲明了兩個(gè)類Boy和Gril,類Boy聲明為類Gril的友元,因此類Boy的成員
函數(shù)都能成為類Gril的友元函數(shù),它們都可以訪問類Gril的私有成員。
例 3.36 友元類的應(yīng)用
注意:聲明一個(gè)類A為另一個(gè)類B的友元類(則類A的所有成員函數(shù)都是類B的友元函數(shù),友元類A的所有成員函數(shù)既可以訪問自己本類的所有成員,也可以訪問類B的所有成員)
#include<iostream> #include<string> using namespace std; class Gril; //對(duì)友元類的提前引用聲明 class Boy{public:Boy(char* n,int a){name=new char[strlen(n)+1];strcpy(name,n);age = a;} ~Boy(){delete []name;}void display(Gril &); //聲明函數(shù)display為類Boy的成員函數(shù) private:char* name;int age; }; class Gril{public:Gril(char* n,int a){name=new char[strlen(n)+1];strcpy(name,n);age = a;} ~Gril(){delete []name;} friend class Boy; //聲明Boy為類Gril的友元類,則類Boy中的所有成員函數(shù)為Gril類的友元成員函數(shù) private:char* name;int age; }; void Boy::display(Gril &x) {cout<<"男孩的姓名是:"<<name<<endl;cout<<"男孩的年齡是:"<<age<<endl;cout<<"女孩的姓名是:"<<x.name<<endl;cout<<"女孩的年齡是:"<<x.age<<endl; } int main() {Boy b("陳大林",11);Gril g("張曉好",12);b.display(g);return 0; } /*說明:友元關(guān)系是單向的,不具有交換性。若聲明了類X是類Y的友元類(即在類Y定義中聲明X為friend類),不等于類Y一定是X的友元,這就要看在類X中是否有相應(yīng)的聲明。友元關(guān)系也不具有傳遞性,若類X是類Y的友元,類Y是類Z的友元,不一定類X是類Z的友元。如果想讓類X是類Z的友元類,應(yīng)在類Z中作出聲明。 */?
轉(zhuǎn)載于:https://www.cnblogs.com/XYQ-208910/p/4912261.html
總結(jié)
以上是生活随笔為你收集整理的C++:友元(非成员友元函数、成员友元函数、友元类)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你可以不知道原因,但是,我们不能停止努力
- 下一篇: 理解javascript闭包