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