2.11 友元
类的封装具有信息的隐藏能力,但也带来了访问效率的问题. C++通过友元给某些函数一项特权,可以访问类中的私有成员,使用的关键字是friend。
2.11.1 友元函数
友元函数可以直接访问类的私有成员
class X{
frient T f(...); //声明f为X类的友元
...
};
T f(...){} //友元不是类的成员函数
#include <iostream>
#include <cmath>
using namespace std;
class point{
private:
int x, y;
public:
point(int a = 10, int b = 20) {
x = a;
y = b;
}
int getx(){
return x;
}
int gety(){
return y;
}
friend double dist2(const point& p1, const point& p2); //创建友元函数
};
double dist1(point& p1, point& p2) { //普通函数
double X = p2.getx() - p1.getx();
double Y = p2.gety() - p2.gety();
return sqrt(X*X + Y*Y);
}
double dist2(const point& p1, const point& p2){ //调用友元函数
double X = p2.x - p1.x; //类外可以直接访问到 point类 中的私有成员
double Y = p2.y - p2.y;
return sqrt(X*X + Y*Y);
}
int main(void) {
point p1(5,8), p2(9,3);
cout << dist1(p1, p2) << endl;
cout << dist2(p1, p2) << endl;
return 0;
}
2.11.2 友元类
一个类可以是另一个类的友元,友元类的所有成员函数都是另一个类的友元函数,能够直接访问另一个类的所有成员。
#include <iostream>
using namespace std;
class A {
private:
int A_x, A_y;
public:
A(int a, int b) {
A_x = a;
A_y = b;
}
int getx() {
return A_x;
}
int gety() {
return A_y;
}
friend class B; //声明B是A的友元类
};
class B{
private:
int B_x, B_y;
public:
B(int a, int b) {
B_x = a;
B_y = b;
}
int add(const A& a){
return a.A_x + a.A_y + B_x + B_y;
}
int sub(const A& a){
return a.A_x - a.A_y - B_x - B_y;
}
};
int main(void) {
A a(3,5);
B b(6,9);
cout << b.add(a) << endl;
cout << b.sub(a) << endl;
return 0;
}
友元类不是双向的:B是A的友元类,不意味着A也是B的友元类
2.11.3 友元成员函数
对一个类,可以指定他的某个成员函数是另一个类的友元,也就是友元成员函数。
#include <iostream>
using namespace std;
class A;
class B{
private:
int B_x, B_y;
public:
B(int a, int b) {
B_x = a;
B_y = b;
}
int add(const A& );
int sub(const A& );
};
class A {
private:
int A_x, A_y;
public:
A(int a, int b) {
A_x = a;
A_y = b;
}
int getx() {
return A_x;
}
int gety() {
return A_y;
}
friend int B::add(const A&); //声明 B 类中的add() 函数是 A 类中的友元
};
int B::add(const A& a){
return a.A_x + a.A_y + B_x + B_y;
}
int B::sub(const A& a){
// return a.A_x - a.A_y - B_x - B_y;
}
int main(void) {
A a(3,5);
B b(6,9);
cout << b.add(a) << endl;
// cout << b.sub(a) << endl;
return 0;
}