由于C++类的封装性,所以类的私有成员只能在类的内部访问,类之外是不能访问他们的。但是如果将其他类设置为类的友元(friend),那么其他类也可以访问该类的私有成员。如果把类比作是一个家庭的话,那么private就是这个家庭的秘密,一般的外人是不能知道这些秘密的,只有friend才能知道这些秘密。
一.友元的形式
1.友元函数之全局函数
#include <iostream>
#include <math.h>
using std::cout;
using std::endl;
using std::cin;
class Point
{
private:
int _x;
int _y;
//友元函数不是类的成员函数
friend double distance(const Point& x_rhs,const Point& y_rhs);
public:
Point(int a,int b)
:_x(a)
,_y(b)
{
cout<<"Point()"<<endl;
}
~Point()
{
cout<<"~Point()"<<endl;
}
};
double distance(const Point& x_rhs,const Point& y_rhs)
{
return hypot(x_rhs._x-x_rhs._y,y_rhs._x-y_rhs._y);
}
int main()
{
Point a(2,3);
Point b(3,4);
cout<<distance(a,b)<<endl;
return 0;
}
其中有几点需要注意:
1.类中的友元函数不是该类的成员函数。也就是说友元函数不含有this指针。
2.hypot(a,b)函数是将a^2+b^2开平方。
2.友元函数之成员函数
#include <iostream>
#include <math.h>
using std::cin;
using std::cout;
using std::endl;
class Point;
class Line
{
public:
double distance(const Point &rhs1, const Point &rhs2);
void setPoint(Point& pt,int _x,int _y);
};
class Point
{
private:
int _x;
int _y;
friend double Line::distance(const Point &rhs1, const Point &rhs2);
friend void Line::setPoint(Point& pt,int _x,int _y);
public:
Point(int a, int b)
: _x(a), _y(b)
{
cout << "Point()" << endl;
}
~Point()
{
cout << "~Point()" << endl;
}
};
double Line::distance(const Point &rhs1, const Point &rhs2)
{
return hypot(rhs2._x - rhs1._x, rhs2._y - rhs1._y);
}
void Line::setPoint(Point& pt,int _x,int _y)
{
pt._x=_x;
pt._y=_y;
}
int main()
{
Point a(1,2);
Point b(2,3);
cout<<Line().distance(a,b)<<endl;
return 0;
}
有几点需要注意的是:
在设置类的成员函数为友元时,要注意如果在第一个类中使用了一个未定义的类时需要提前声明,其中class Point;就是这个作用。但是如果继续在class Line{ };中 将成员函数double distance(const Point &rhs1, const Point &rhs2);都实现就会报
因为声明类class Point;时,只是告诉编译器有这个类,但是并不知道这个类中的成员函数。因此需要将成员函数的实现放在类class Point;实现的后面,如代码所示。
3.友元函数之友元类
如上面的代码所示,类 class Line中所有的成员函数都是类class Point; 的友元,我们就可以把类class Line设置成友元类。
将代码
替换成
总结:
1.友元的声明是不受关键字private,public,protect限制的,并且友元的关系是不能传递的
2.友元是单向的,如A是B的友元,但B不一定是A的友元
3.友元关系不能被继承。
由于友元会破坏类的封装性,所以要谨慎使用。