友元:打破数据隐藏机制,能够在类的外部访问该类的私有成员。
包括友元函数和友元类。
友元函数:
必须在类的定义中声明,前面必须加friend关键字。
与一般成员函数区别:友元函数需要通过对象访问类的成员(一般成员函数直接访问),而为了能够访问或修改类的私有成员,一般以该类的对象的引用作为函数参数。友元声明可以放在类定义的任何地方,不受访问权限控制符的影响。
#include <iostream>
#include <cmath>
using namespace std;
class Point;
class Dist{
public:
float GetDistance(Point, Point);
};
class Point{
private:
int x, y;
public:
Point(int x = 0, int y = 0):x(x),y(y)
{
cout << "Point construction: " << x << ", "<< y << endl;
}
Point(Point &p) // copy constructor,其实数据成员是int类型,默认也是一样的
{
x = p.x;
y = p.y;
cout << "Point copy construction: " << x << ", "<< y << endl;
}
int getX(){ return x; }
int getY(){ return y; }
friend float GetDistance(Point, Point);// 友元声明,一般友元
friend float Dist::GetDistance(Point, Point);// 友元声明,友元函数是类Dist的public成员函数
};
float GetDistance(Point p1, Point p2)
{
double dx = p1.x - p2.x;
double dy = p1.y - p2.y;
return (float)(sqrt)(dx*dx+dy*dy);
}
float Dist::GetDistance(Point p1, Point p2)
{
double dx = p1.x - p2.x;
double dy = p1.y - p2.y;
return (float)(sqrt)(dx*dx+dy*dy);
}
int main()
{
Point p1(10,20),p2(100,200);
cout << "The distance is: "<<GetDistance(p1,p2)<<endl;
Dist d;
cout << "Dist: The distance is: "<<d.GetDistance(p1,p2)<<endl;
}
输出:
Point construction: 10, 20
Point construction: 100, 200
Point copy construction: 100, 200
Point copy construction: 10, 20
The distance is: 201.246
Point copy construction: 100, 200
Point copy construction: 10, 20
Dist: The distance is: 201.246
友元类:
一个类可以声明另一个类为其友元类(You are my firend who I trust. )类A声明类B是自己的友元类,则B的所有成员函数可以访问A的私有成员(public是本来就可以)。
class A;
class B{
private: int x;
public: void BMemFunc(A &);
};
class A{
friend B; // 注意写法,是写B的类名
private:
int a, b;
public:
A(int x=0, int y = 0):a(x),b(y){}
void display(){
cout << "a=" << a <<", b="<< b << endl;
}
};
void B::BMemFunc(A &objA)
{
objA.a = 20; // 访问修改A类的对象 objA的私有成员a
}
总结:友元方便了不同类或不同类的成员函数之间,以及成员函数和一般函数之间的数据共享,但也破坏了类的封装性。
PS: 友元关系是单方向的,不具有交换性和传递性。比如本例中的A不是B的友元类,A不能访问B的私有成员。