具體來說:爲了使其他類的成員函數直接訪問該類的私有變量
即:允許外面的類或函數去訪問類的私有變量和保護變量,從而使兩個類共享同一函數
優點:能夠提高效率,表達簡單、清晰
缺點:友元函數破環了封裝機制,儘量不使用成員函數,除非不得已的情況下才使用友元函數。
2、什麼時候使用友元函數:
1)運算符重載的某些場合需要使用友元。
2)兩個類要共享數據的時候
3、怎麼使用友元函數:
友元函數的參數:
因爲友元函數沒有this指針,則參數要有三種情況:
1、 要訪問非static成員時,需要對象做參數;--常用(友元函數常含有參數)
2、 要訪問static成員或全局變量時,則不需要對象做參數
3、 如果做參數的對象是全局對象,則不需要對象做參數
友元函數的位置:
因爲友元函數是類外的函數,所以它的聲明可以放在類的私有段或公有段且沒有區別。
友元函數的調用:
可以直接調用友元函數,不需要通過對象或指針
友元函數的分類:
根據這個函數的來源不同,可以分爲三種方法:
1、普通函數友元函數:
a) 目的:使普通函數能夠訪問類的友元
b) 語法:聲明位置:公有私有均可,常寫爲公有
聲明: friend + 普通函數聲明
實現位置:可以在類外或類中
實現代碼:與普通函數相同(不加不用friend和類::)
調用:類似普通函數,直接調用
c) 代碼:
- class INTEGER
- {
- private:
- int num;
- public:
- friend void Print(const INTEGER& obj);//聲明友元函數
- };
- void Print(const INTEGER& obj)//不使用friend和類::
- {
- //函數體
- }
- void main()
- {
- INTEGER obj;
- Print(obj);//直接調用
- }
2、類Y的所有成員函數都爲類X友元函數—友元類
a)目的:使用單個聲明使Y類的所有函數成爲類X的友元
它提供一種類之間合作的一種方式,使類Y的對象可以具有類X和類Y的功能
具體來說:
前提:A是B的友元(=》A中成員函數可以訪問B中有所有成員,包括私有成員和公有成員--老忘)
則:在A中,藉助類B,可以直接使用~B . 私有變量~的形式訪問私有變量
b)語法:聲明位置:公有私有均可,常寫爲私有(把類看成一個變量)
聲明: friend + 類名---不是對象啊
調用:
c)代碼:
- class girl;
- class boy
- {
- private:
- char *name;
- int age;
- public:
- boy();
- void disp(girl &);
- };
- void boy::disp(girl &x) //函數disp()爲類boy的成員函數,也是類girl的友元函數
- {
- cout<<"boy's name is:"<<name<<",age:"<<age<<endl;//正常情況,boy的成員函數disp中直接訪問boy的私有變量
- cout<<"girl's name is:"<<x.name<<",age:"<<x.age<<endl;
- //藉助友元,在boy的成員函數disp中,藉助girl的對象,直接訪問girl的私有變量
- //正常情況下,只允許在girl的成員函數中訪問girl的私有變量
- }
- class girl
- {
- private:
- char *name;
- int age;
- friend boy; //聲明類boy是類girl的友元
- public:
- girl();
- };
- void main()
- {
- boy b;
- girl g;
- b.disp(g); //b調用自己的成員函數,但是以g爲參數,友元機制體現在函數disp中
- }
3、類Y的一個成員函數爲類X的友元函數
a)目的:使類Y的一個成員函數成爲類X的友元
具體而言:而在類Y的這個成員函數中,藉助參數X,可以直接以X。私有變量的形式訪問私有變量
b)語法:聲明位置:聲明在公有中 (本身爲函數)
聲明:friend + 成員函數的聲明
調用:先定義Y的對象y---使用y調用自己的成員函數---自己的成員函數中使用了友元機制
c)代碼:
- class girl;
- class boy
- {
- private:
- char *name;
- int age;
- public:
- boy();
- void disp(girl &);
- };
- class girl
- {
- private:
- char *name;
- int age;
- public:
- girl(char *N,int A);
- friend void boy::disp(girl &); //聲明類boy的成員函數disp()爲類girl的友元函數
- };
- void boy::disp(girl &x)
- {
- cout<<"boy's name is:"<<name<<",age:"<<age<<endl; //訪問自己(boy)的對象成員,直接訪問自己的私有變量
- cout<<"girl's name is:"<<x.name<<",age:"<<x.age<<endl;
- //藉助友元,在boy的成員函數disp中,藉助girl的對象,直接訪問girl的私有變量
- //正常情況下,只允許在girl的成員函數中訪問girl的私有變量
- }
- void main()
- {
- boy b();
- girl g();
- b.disp(g); }
4、在模板類中使用友元operator<<(對<<運算符的重載)
a)使用方法:
在模板類中聲明:
- friend ostream& operator<< <>(ostream& cout,const MGraph<VexType,ArcType>& G);
在模板類中定義:
- template<class VexType,class ArcType>
- ostream& operator<<(ostream& cout,const MGraph<VexType,ArcType>& G)
- {
- //函數定義
- }
b)注意:
把函數聲明非模板函數:
- friend ostream& operator<< (ostream& cout,const MGraph& G);
把函數聲明爲模板函數:
- friend ostream& operator<< <>(ostream& cout,const MGraph<VexType,ArcType>& G);
或:
- friend ostream& operator<< <VexType,ArcType>(ostream& cout,const MGraph<VexType,ArcType>& G);
說明:
在函數聲明中加入operator<< <>:是將operator<<函數定義爲函數模板,將函數模板申明爲類模板的友員時,是一對一綁定的
實際的聲明函數:這裏模板參數可以省略,但是尖括號不可以省略
- friend ostream& operator<< <VexType,ArcType>(ostream& cout,const MGraph<VexType,ArcType>& G);
5、友元函數和類的成員函數的區別:成員函數有this指針,而友元函數沒有this指針。
6、記憶:A是B的友元《=》A是B的朋友《=》藉助B的對象,在A中可以直接 通過B。成員變量(可以是公有,也可以爲私有變量) 的方式訪問B