第4章 友元
本章学习要点
深入掌握友元函数的相关概念和使用方法。
深入掌握友元类的相关概念和使用方法。
灵活运用友元的相关知识进行综合程序设计。
4.1 基本知识点
4.1.1 友元函数
友元函数是一种特殊的函数,它需要在类体内进行说明,可以访问类的私有成员,但又不是类的成员函数。友元函数的说明格式如下:
- friend 数据类型 函数名(参数表)
其中,friend是说明友元函数的关键字。
归纳起来,友元函数是一种能够访问类中的私有成员的非成员函数。友元函数在定义上和调用上与普通函数一样。
友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。因此,只有在十分需要时才使用友元函数。
例如,分析下列程序的输出结果。
- #include <iostream.h>
- #include <math.h>
- class TPoint
- { double x,y; //私有数据成员
- public:
- TPoint(double a,double b) //构造函数
- { x=a,y=b; cout << "点:(" << x << "," << y << ")" << endl; }
- friend double distance(TPoint &a,TPoint &b) //友元函数
- {
- return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
- }
- };
- void main()
- { TPoint p1(2,2),p2(5,5);
- cout << "上述两点之间的距离:" //调用友元函数
- << distance(p1,p2) << endl;
- }
在上述程序中,distance()是类TPoint的友元函数,在其中可以直接使用a.x等,由于x等是类TPoint的私有成员,所以在普通函数中是不能这样使用的。调用友元函数distance(p1,p2)时也不需要加上对象前缀。该程序执行结果如下:
- 点:(2,2)
- 点:(5,5)
- 上述两点之间的距离:4.24264
友元函数的一个重要特征是它可以是多个类的友元。
例如,编写一个程序,求一个点到直线的距离。
设计一个点类Point,它有两个私有数据成员x和y,表示点的坐标。另一个类为直线类Line,它有三个私有数据成员a、b和c,表示直线方程ax+by+c=0。这两个类中都说明了一个友元函数dist,用于计算一个点到直线的距离。点(x,y)到直线ax+by+c=0的距离d的计算公式如下:

求解程序如下:
- #include <iostream.h>
- #include <math.h>
- class Line; //提前说明
- class Point
- { int x,y;
- public:
- Point(int x1,int y1)
- { x=x1; y=y1; }
- friend double dist(Line l,Point p); //友元函数声明
- };
- class Line
- { int a,b,c;
- public:
- Line(int a1,int b1,int c1)
- { a=a1; b=b1; c=c1; }
- friend double dist(Line l,Point p); //友元函数声明
- };
- double dist(Line l,Point p) //计算点对象p到直线对象l之间的距离
- { double d;
- d=abs(l.a*p.x+l.b*p.y+l.c)/(sqrt(l.a*l.a+l.b*l.b));
- return d;
- }
- void main()
- { Point p(10,10);
- Line l(2,4,-3);
- cout << "d=" << dist(l,p) << endl;
- }
上述程序中有两个类Point和Line,它们都说明了同一友元函数:friend double dist(Line l,Point p)。由于在Point类中说明时尚未定义Line类,所以需要在前面用class Line;语句进行提前说明。该程序的执行结果如下:
- d=12.7456
一个类A的成员函数f()可以作为另一个类B的友元函数,在这种情况下,必须先定义A类,并且在B类中说明友元函数f()时,要加上成员函数所在类的类名,即:
- class A
- { …
- 数据类型 f(参数表);
- …
- }
- class B
- { …
- friend 数据类型 A::f(参数表);
- …
- }
- 数据类型 A::f(参数表)
- {
- 函数体;
- }