友元提供了不一樣類的成員函數之間、類的成員函數與通常函數之間進行數據共享的機制。經過友元,一個不一樣函數或另外一個類中的成員函數能夠訪問類中的私有成員和保護成員。c++中的友元爲封裝隱藏這堵不透明的牆開了一個小孔,外界能夠經過這個小孔窺視內部的祕密。html
友元的正確使用能提升程序的運行效率,但同時也破壞了類的封裝性和數據的隱藏性,致使程序可維護性變差。ios
友元函數是能夠直接訪問類的私有成員的非成員函數。它是定義在類外的普通函數,它不屬於任何類,但須要在類的定義中加以聲明,聲明時只需在友元的名稱前加上關鍵字friend,其格式以下: 函數
友元函數的聲明能夠放在類的私有部分,也能夠放在公有部分,它們是沒有區別的,都說明是該類的一個友元函數。
一個函數能夠是多個類的友元函數,只須要在各個類中分別聲明。
友元函數的調用與通常函數的調用方式和原理一致。spa
友元類 :
友元類的全部成員函數都是另外一個類的友元函數,均可以訪問另外一個類中的隱藏信息(包括私有成員和保護成員)。
當但願一個類能夠存取另外一個類的私有成員時,能夠將該類聲明爲另外一類的友元類。定義友元類的語句格式以下:
friend class 類名;
其中:friend和class是關鍵字,類名必須是程序中的一個已定義過的類。.net
1: #include <iostream>
2: using namespace std;
3:
4: class Radius
5: {
6: friend class Circle; //聲明Circle爲Radius的友元類
7: friend void Show_r(Radius &n); //聲明Show_r爲友元函數
8: public:
9: Radius(int x)
10: {
11: r = x;
12: }
13: ~Radius()
14: {
15: }
16:
17: private:
18: int r;
19: };
20:
21: void Show_r(Radius &n)
22: {
23: cout<<"圓的半徑爲: "<<n.r<<endl; //調用Radius對象的私有成員變量r
24: }
25:
26: class Circle
27: {
28: public:
29: Circle() {}
30: ~Circle(){}
31: double area(Radius a)
32: {
33: s = a.r * a.r * 3.1415926; //調用Radius對象的私有成員變量r
34: return s;
35: }
36: private:
37: double s;
38: };
39:
40: int main(int argc, char *argv[])
41: {
42: Radius objRadius(9);
43: Circle objCircle;
44:
45: Show_r( objRadius );
46: cout<<"面積爲:"<<objCircle.area(objRadius)<<endl;
47:
48: return 0;
49: }
若是咱們決定一個函數必須被聲明爲兩個類的友元則友元聲明以下code
1: class Window; // 只聲明
2:
3: class Screen
4:
5: {
6:
7: friend bool is_equal( Screen &, Window & );
8:
9: // ...
10:
11: };
12:
13: class Window
14:
15: {
16:
17: friend bool is_equal( Screen &, Window & );
18:
19: // ...
20:
21: };
若是咱們決定該函數必須做爲一個類的成員函數並又是另外一個類的友元,則成員函數聲明和友元聲明以下:htm
1: class Window;
2:
3: class Screen
4:
5: {
6:
7: public:
8:
9: // copy 是類 Screen 的成員
10:
11: Screen& copy( Window & );
12:
13: // ...
14:
15: };
16:
17: class Window
18:
19: {
20:
21: // copy 是類 Window 的一個友元
22:
23: friend Screen& Screen::copy( Window & );
24:
25: // ...
26:
27: };
只有當一個類的定義已經被看到時它的成員函數才能被聲明爲另外一個類的友元。這並不老是可以作到的。對象
例如若是Screen 類必須把Window 類的成員函數聲明爲友元,而Window類必須把Screen 類的成員函數聲明爲友元。該怎麼辦呢?在這種狀況下能夠把整個Window類聲明爲Screen 類的友元。blog
例如:
1: class Window;
2:
3: class Screen
4:
5: {
6:
7: friend class Window;
8:
9: // ...
10:
11: };
Screen 類的非公有成員如今能夠被Window 的每一個成員函數訪問。
使用友元類時注意:
(1) 友元關係不能被繼承。 (2) 友元關係是單向的,不具備交換性。若類B是類A的友元,類A不必定是類B的友元,要看在類中是否有相應的聲明。 (3) 友元關係不具備傳遞性。若類B是類A的友元,類C是B的友元,類C不必定是類A的友元,一樣要看類中是否有相應的申明