C++——友元函数--友元类——friend关键字
一、友元函数
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 }