一、友元函數
1、友元函數允許在類外訪問該類中的任何成員,使用關鍵字friend說明。通過友元一個普通函數或類的成員函數可以訪問封裝於另一個類中的數據。從一定程度上講,友元是對數據隱藏和封裝的破壞,但是為了數據共享和提高程序的效率與可讀性,小的破壞是必要的。
友元函數不屬於該類的成員函數,它是定義在類外的普通函數,只是在類中通過friend關鍵字聲明,從而使該函數可以訪問類中的private與protected成員
2.友元函數的聲明一般形式:
-
friend <返回值類型> <函數名> (<參數列表>)
3.使用友元函數注意的要點
- 1---類中通過使用關鍵字friend來說明友元函數,但該函數並不是類的成員函數,其聲明可以放在類的私有部分也可以放在類的公有部分。友元函數的定義在類體外實現,不需要加類限定。
- 2---一個類的成員函數可以是另一個類的友元函數,而且一個函數可以是多個類的友元函數。
- 3---友元函數可以訪問類的私有成員和數據,但是可以訪問但不能直接使用數據成員需要通過對對象進行引用使用數據成員
- 4---友元函數在調用上同一般函數一樣,不必通過對對象進行引用
對於1、2、4、的使用解釋詳見下面代碼:
-
class persion{ public: persion(char *pn); //友元函數; friend void setweigth(persion &p,int h);//注意,參數列表中一般會有一個引用類型的形參,原因參考上面的使用要點3和4; void disp(); //類成員函數 private: char name[20]; int weigth,age; }; persion::persion(char *pn) //構造函數 { strcpy(name,pn); weigth=0; } void persion::disp() { cout<<name<<"--"<<weigth<<endl; } //友元函數的具體實現:這里沒有類限定例如 (perion::setweigth)這種形式,這里可以與上面的disp()做個對比,一個屬於類的成員,有限定,一個不屬於類的成員函數,沒有加限定。 void setweigth(persion &pn,int w) { pn.weigth=w; //私有成員數據賦值 } void main() { persion p("zhansan"); setweigth(p,60);//調用實現setweigth(),與一般函數調用一致。 p.disp(); //調用類的成員函數。 }
對於第2點的使用詳見下邊的代碼:一個類的成員函數可以是另一個類的友元函數
-
1 class wheel; 2 class car{ 3 public: 4 car(char *pn); 5 void run(wheel &w); //成員函數,做成wheel類中友元函數實現 6 private: 7 char name[20]; 8 9 }; 10 car::car(char *pn) 11 { 12 strcpy(name,pn); 13 } 14 15 class wheel{ 16 public: 17 wheel(int s); 18 friend void car::run(wheel &w); //這里把car類的成員函數做了友元函數。 19 private: 20 int speed; 21 }; 22 wheel::wheel(int s) 23 { 24 speed=s; 25 } 26 27 void car::run(wheel &w) //car類成員函數的實現 28 { 29 cout<<"the car is running"<<endl; 30 cout<<"name: "<<name<<" speed :"<<w.speed<<endl; 31 } 32 33 int main(int argc, char const *argv[]) 34 { 35 wheel w(60); 36 car c("New car"); 37 c.run(w); //通過car的成員函數作為友元函數訪問類wheel類中的數據成員 38 return 0; 39 }
- 使用友元函數計算兩點之間的距離:代碼示例如下
-
1 #include <iostream> 2 #include <cmath> 3 using namespace std; 4 //使用友元函數計算兩點之間的距離 5 class Point{ 6 public: 7 Point(int xx = 0, int yy = 0) { X = xx; Y = yy;} 8 int GetX() {return X;} 9 int GetY() {return Y;} 10 friend float fDist( Point &a, Point &b ); 11 private: 12 int X, Y; 13 }; 14 15 float fDist(Point &p1, Point &p2){ 16 double x = double(p1.X - p2.X);//通過對象訪問私有數據成員,而不是必須使用Getx()函數 17 double y = double(p1.Y - p2.Y); 18 return float(sqrt(x*x + y*y)); 19 } 20 int main(){ 21 Point p1(1, 1), p2(4, 5); 22 cout << "the distance is:"; 23 cout << fDist(p1, p2) << endl;//計算兩點之間的距離 24 return 0; 25 }
友元函數直接使用了對象名訪問了私有數據成員X,Y,而不是通過類的成員函數Getx(),Gety(),函數。
-
二、友元類
1、和友元函數一樣,一個類也可以聲明為另一個類的友元類。聲明為友元的類可以訪問該類的私有數據成員,該類的成員函數都是該友元類的成員函數
- 友元類的應用詳見下邊代碼:
-
1 class A{ 2 public: 3 int GetX() { return x; } 4 friend class B;//B類是A類的友元類 5 //其它成員略 6 private: 7 int x; 8 }; 9 class B{ 10 public: 11 void set(int i); 12 //其他成員略 13 private: 14 A a; 15 }; 16 void B :: set(int i){ 17 a.x = i;//由於B類是A類的友元類,所以在B的成員函數中可以訪問A類對象的私有成員 18 }