1、友元关系的引入
考虑一个问题,对于一个Point类,用来保存一个坐标,即它有两个实数型变量是它的坐标,那么我们现在想要计算点与点之间的距离,这个函数要放在哪里比较合适?
①放在类中作为类的成员函数吗?但是这个函数不属于单独的一个点,也不属于Point类。
②放在类的外面定义为普通函数吗?但是这样就体现不了这个函数与Point类的关系,并且不能直接访问点的坐标(私有成员)
所以这里就引入了友元关系
友元关系:提供了不同类或对象的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制
也就是说通过友元关系,一个类的成员函数或者一个普通函数可以去访问封装在另一个类中的私有数据。
在一定程度上,友元关系是对数据隐蔽和封装的破坏,但是为了数据共享和可读性,小的破坏也是有必要的
2、友元函数
友元函数就是在类中,用friedn修饰非成员函数,它的意思是这个函数是这个类的朋友,可以访问这个类的所有东西。
下面的代码实现了一个普通函数dist与Point类的友元关系。
dist函数的函数体可以通过对象名访问Point类的私有数据。
#include<bits/stdc++.h>
using namespace std;
class Point{
public:
Point(double x=0,double y=0);
friend double dist(Point &a,Point &b);
private:
double x,y;
};
Point::Point(double xx,double yy):x(xx),y(yy){
}
double dist(Point &a, Point &b){
double x=a.x-b.x;
double y=a.y-b.y;
return sqrt(x*x+y*y);
}
int main(){
Point a,b(3.0,4.0);
cout<<dist(a,b);
return 0;
}
3、友元类
若类A是类B的友元类,那么A中所有成员函数都是B的友元函数,都可以访问B中的私有和保护成员
下面代码中,在类Point中说明了类Line是它的友元类,所以类Line中的所有成员函数都是类Point的友元函数,都能访问类Point中的所有私有成员
#include<bits/stdc++.h>
using namespace std;
class Point{
public:
Point(double x=0.0,double y=0.0);
friend double dist(Point &a,Point &b);
friend class Line;
private:
double x,y;
};
Point::Point(double xx,double yy):x(xx),y(yy){
}
double dist(Point &a, Point &b){
double x=a.x-b.x;
double y=a.y-b.y;
return sqrt(x*x+y*y);
}
class Line{
public:
Line();
Line(Point &a,Point &b){
this->a=a;
this->b=b;
}
void display(){
cout<<a.x<<" "<<a.y<<endl;
cout<<b.x<<" "<<b.y<<endl;
cout<<dist(a,b)<<endl;
}
private:
Point a,b;
};
int main(){
Point a,b(3.5,4.5);
Line c(a,b);
c.display();
return 0;
}
4、注意事项
①友元关系不能传递,A是B的友元,C是A的友元,如果C和B之间没有声明友元关系,那么C不是B的友元,不能访问B的私有成员。
②友元关系是单向的,A是B的友元,如果在A中没有声明的话,那么B不是A的友元。比如小明把小亮当朋友,所以小亮可以去小明家玩,但是小亮不把小明当朋友,所以小明不能去小明家玩。
③友元不会被继承。别人相信你,但不一定相信你的孩子。