有些狀況下,容許特定的非成員函數訪問一個類的私有成員,同時仍阻止通常的訪問,這是很方便作到的。例如被重載的操做符,如輸入或輸出操做符,常常須要訪問類的私有數據成員。ios
友元(frend)機制容許一個類將對其非公有成員的訪問權授予指定的函數或者類,友元的聲明以friend開始,它只能出如今類定義的內部,友元聲明能夠出如今類中的任何地方:友元不是授予友元關係的那個類的成員,因此它們不受其聲明出現部分的訪問控制影響。一般,將友元聲明成組地放在類定義的開始或結尾是個好主意。編程
友元函數是指某些雖然不是類成員函數卻可以訪問類的全部成員的函數。類授予它的友元特別的訪問權,這樣該友元函數就能訪問到類中的全部成員。函數
#include <iostream> using namespace std; class A { public: friend void set_show(int x, A &a); //該函數是友元函數的聲明 private: int data; }; void set_show(int x, A &a) //友元函數定義,爲了訪問類A中的成員 { a.data = x; cout << a.data << endl; } int main(void) { class A a; set_show(1, a); return 0; }
友元類的全部成員函數都是另外一個類的友元函數,均可以訪問另外一個類中的隱藏信息(包括私有成員和保護成員)。當但願一個類能夠存取另外一個類的私有成員時,能夠將該類聲明爲另外一類的友元類。spa
關於友元類的注意事項:.net
(1) 友元關係不能被繼承。
(2) 友元關係是單向的,不具備交換性。若類B是類A的友元,類A不必定是類B的友元,要看在類中是否有相應的聲明。
(3) 友元關係不具備傳遞性。若類B是類A的友元,類C是B的友元,類C不必定是類A的友元,一樣要看類中是否有相應的申明。code
#include <iostream> using namespace std; class A { public: friend class C; //這是友元類的聲明 private: int data; }; class C //友元類定義,爲了訪問類A中的成員 { public: void set_show(int x, A &a) { a.data = x; cout<<a.data<<endl;} }; int main(void) { class A a; class C c; c.set_show(1, a); return 0; }
使類B中的成員函數成爲類A的友元函數,這樣類B的該成員函數就能夠訪問類A的全部成員了。blog
當用到友元成員函數時,需注意友元聲明和友元定義之間的相互依賴,在該例子中,類B必須先定義,不然類A就不能將一個B的函數指定爲友元。然而,只有在定義了類A以後,才能定義類B的該成員函數。更通常的講,必須先定義包含成員函數的類,才能將成員函數設爲友元。另外一方面,沒必要預先聲明類和非成員函數來將它們設爲友元。繼承
#include <iostream> using namespace std; class A; //當用到友元成員函數時,需注意友元聲明與友元定義之間的互相依賴。這是類A的聲明 class B { public: void set_show(int x, A &a); //該函數是類A的友元函數 }; class A { public: friend void B::set_show(int x, A &a); //該函數是友元成員函數的聲明 private: int data; void show() { cout << data << endl; } }; void B::set_show(int x, A &a) //只有在定義類A後才能定義該函數,畢竟,它被設爲友元是爲了訪問類A的成員 { a.data = x; cout << a.data << endl; } int main(void) { class A a; class B b; b.set_show(1, a); return 0; }
在須要容許某些特定的非成員函數訪問一個類的私有成員(及受保護成員),而同時仍阻止通常的訪問的狀況下,友元是可用的。get
優勢:it
能夠靈活地實現須要訪問若干類的私有或受保護的成員才能完成的任務;
便於與其餘不支持類概念的語言(如C語言、彙編等)進行混合編程;
經過使用友元函數重載能夠更天然地使用C++語言的IO流庫。
缺點:
一個類將對其非公有成員的訪問權限授予其餘函數或者類,會破壞該類的封裝性,下降該類的可靠性和可維護性。
參考資料:
一、《C++ Prime》第4版 第12章類的友元小節
http://blog.csdn.net/u012796139/article/details/46404401