標籤:
友元提供了不同類的成員函數之間、類的成員函數與一般函數之間進行資料共用的機制。通過友元,一個不同函數或另一個類中的成員函數可以訪問類中的私人成員和保護成員。C++中的友元為封裝隱藏這堵不透明的牆開了一個小孔,外界可以通過這個小孔窺視內部的秘密。友元的正確使用能提高程式的運行效率,但同時也破壞了類的封裝性和資料的隱藏性,導致程式可維護性變差。
友元函數
友元函數是可以直接存取類的私人成員的非成員函數。它是定義在類外的普通函數,它不屬於任何類,但需要在類的定義中加以聲明,聲明時只需在友元的名稱前加上關鍵字friend,其格式如下:
friend 類型 函數名(形式參數);
友元函數的聲明可以放在類的私人部分,也可以放在公有部分,它們是沒有區別的,都說明是該類的一個友元函數。一個函數可以是多個類的友元函數,只需要在各個類中分別聲明。友元函數的調用與一般函數的調用方式和原理一致。
友元類
友元類的所有成員函數都是另一個類的友元函數,都可以訪問另一個類中的隱藏資訊(包括私人成員和保護成員)。當希望一個類可以存取另一個類的私人成員時,可以將該類聲明為另一類的友元類。定義友元類的語句格式如下:
friend class 類名;
例如:當一個類B成為了另外一個類A的“朋友”時,那麼類A的私人和保護的資料成員就可以被類B訪問。我們就把類B叫做類A的友元。
使用友元類時注意:
(1)友元關係不能被繼承。
(2)友元關係是單向的,不具有交換性。若類B是類A的友元,類A不一定是類B的友元,要看在類中是否有相應的聲明。
(3)友元關係不具有傳遞性。若類B是類A的友元,類C是B的友元,類C不一定是類A的友元,同樣要看類中是否有相應的聲明。
友元執行個體
1 #include <math.h> 2 #include<iostream> 3 using namespace std; 4 class Point 5 { 6 public: 7 Point(double xx, double yy) 8 { 9 x=xx; 10 y=yy; 11 }12 void Getxy(); 13 friend double Distance(Point &a, Point &b); //類Point的友元函數14 friend class Yao; //類Point的友元類15 private: 16 double x, y; 17 }; 18 class Yao19 {20 public:21 double Multi(Point &a)22 {23 return a.x * a.y + 1;24 }25 };26 void Point::Getxy() 27 { 28 cout<<"("<<x<<","<<y<<")"<<endl; 29 } 30 double Distance(Point &a, Point &b) //類Point的友元函數31 { 32 double dx = a.x - b.x; 33 double dy = a.y - b.y; 34 return sqrt(dx*dx+dy*dy); 35 } 36 int main(void) 37 { 38 Point p1(3.0, 4.0), p2(6.0, 8.0); 39 p1.Getxy(); 40 p2.Getxy(); 41 double d = Distance(p1, p2); //Distance是類Point的友元函數,不是成員函數42 cout<<"Distance is "<<d<<endl; 43 Yao yao;44 d = yao.Multi(p1);45 cout<<"Math.Multi is "<<d<<endl;46 return true;47 }
注意事項:
1.友元可以訪問類的私人成員。
2.只能出現在類定義內部,友元聲明可以在類中的任何地方,一般放在類定義的開始或結尾。
3.友元可以是普通的非成員函數,或前面定義的其他類的成員函數,或整個類。
4.類必須將重載函數集中每一個希望設為友元的函數都聲明為友元。
5.友元關係不能繼承,基類的友元對衍生類別的成員沒有特殊的存取權限。如果基類被授予友元關係,則只有基類具有特殊的存取權限。該基類的衍生類別不能訪問授予友元關係的類。
C++之友元