一.来源
下面是一个计算两点之间距离的方法。
#include <iostream >
#include <math.h>
class Point {
private:
int x;
int y;
public:
Point(int x, int y) {
this->x = x;
this->y = y;
}
int getX() {
return x;
}
int getY() {
return y;
}
};
//计算两点之间距离
double distance(Point& p1, Point& p2) {
int X = p1.getX() - p2.getX();//频繁使用getX()
int Y = p1.getY() - p2.getY();//频繁使用getY()
return sqrt(X*X+Y*Y);
}
using namespace std;
int main() {
Point p1(1, 1), p2(2, 2);
cout << distance(p1, p2);
}
可以发现,频繁的调用getX()、getY(),导致频繁的压栈出栈,浪费时间空间。
所以引出友元函数。
友元函数就是为了解决,方便某一个函数频繁使用类中私有成员变量。
二.友元函数
友元函数可以申明在类中任何地方(public、private、protected)
改写上面例子:
class Point {
friend double distance(Point& p1, Point& p2);//申明友元函数
private:
int x;
int y;
public:
Point(int x, int y) {
this->x = x;
this->y = y;
}
int getX() {
return x;
}
int getY() {
return y;
}
};
//计算两点之间距离
double distance(Point& p1, Point& p2) {
int X = p1.x - p2.x;//改写
int Y = p1.y - p2.y;//改写
return sqrt(X*X+Y*Y);
}
using namespace std;
int main() {
Point p1(1, 1), p2(2, 2);
cout << distance(p1, p2);
}
通过增加函数一个声明,就可以在这个声明的函数内部,访问私有成员变量。
friend double distance(Point& p1, Point& p2);
三.友元类
也是为了解决友元函数的问题。
例子:
class A {
private:
int a;
public:
A(int a) {
this->a = a;
}
void print() {
cout << "a=" << a << endl;
}
friend class B;//申明友元类
};
class B {
private:
int b;
public:
B(int b) {
this->b = b;
}
void print() {
A a1(1);
//注意这个地方可以通过友元类访问私有成员变量
cout << "A a1=" << a1.a << endl;
cout << "B b=" << b << endl;
}
};
int main() {
B b1(2);
b1.print();
}
结果:
四.问题
- 友元函数破坏了类的封装,一般不建议使用。
- 友元关系不能被继承。例子:老王是你爸朋友,但不一定是你朋友。
- 友元关系是单向的,不具备交换性。若类B是类A的友元,A不一定是B的友元,关键要看类中是否有相应的申明。