目录
一、概念
作用:
让一个函数或类,访问另一个类的私有成员,从而打破封装
函数O如果想访问类A的私有数据成员,把函数O作为A类的友元就可以访问了,也就是说函数或者类作为另外一个类的友元时,就可以访问该类的private或者protected
使用:
- 只能在类内引用,在外部定义
做法:在函数内部,函数前面加上 friend
如下所示就是把函数Add()作为类A的友元
二、友元的使用
1.怎么解决一个未声明的类作为另一个类的参数情况?
以如下代码为例,函数Add内有两个参数,一个是类A定义的a,一个是类B定义的b。类A在类B前面声明,那么在类A内的友元Add中的B就没有声明。怎么解决这种现象?
做法是:在A前面写个class B;——叫做,前向引用声明
Class B; //前向引用声明
Class A
{
public:
A(int i=0):m_i(i){}
friend int Add(A& a,B& b);
private:
int m_i;
}
Class B
{
public:
B(int j=0):m_j(j){}
friend int Add(A& a,B& b);
protect:
int m_j;
}
int Sum(A& a,B& b)
{
return a.m_i+m.m_j;
}
2. 一个类的成员函数作为另外一个类的友元时怎么写?
B的成员函数m_j,想要访问A的私有数据成员m_i,只要把B的成员函数Sub()作为A的友元即可访问。
friend void Sub(A& a);
但这样写不对,需要写出作用域,是谁的Sub(),因此需要修改为:
friend void B::Sub(A& a);
成员函数在内部声明后,最好放在类外定义,因此需要添加下面代码:
void B::Sub(A& a)
{
}
void Sub(A& a) //err ,这样写A内的Sub是把外部的成员函数调用
{
}
此处引入一个名词——友元函数,即为上例中Sub(),通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。
3.一个类可以作为另外一个类的友元类——友元类
功能:将类作为友元,友元类的所有方法都可以访问原始类的私有成员和保护成员。
4.友元在运算符重载中的作用
运算符重载一般针对相同类型的运算,如果是在不同类内进行操作,需要借助友元。
如下类内的 int operator+()函数。A怎么实现对B里面的数据成员进行访问?
做法是,A把运算符函数作为B的友元。如下,把运算符函数写在A类内,在B类内写友元运算符函数即可。
补充:两个不同类的对象进行相加,首先需要满足的条件:数据成员个数和类型一致。
三、友元的性质
- 友元是单向的。当A作为B的友元时,A可以访问B的私有/保护成员函数,B不可以访问A的私有数据成员。
- 友元不能传递。A作为B的友元,B作为C的友元,A可以访问B的私有/保护成员函数,C可以访问A的私有/保护成员,但是C不可以访问B的私有数据成员。
- 友元不能继承。基类的友元对派生类没有特殊的访问权限。A继承B类型,B是C的友元,但是A不是C的友元。
四、友元函数的三种实现
- 全局函数做友元
- 类做友元
- 成员函数做友元