这个标题我寻思我要不要这么写出来。最终还是写了,那我就围绕标题开始说话
合作关系必须建立在友谊的基础上
- 为什么会有friend?
friend的建立,通常是为了效率考虑。类与类之间的或类与某非成员函数之间的简单的操作我们不需要friend比如数据成员的读写,我们可以给数据成员的读写这种操作提供具有public访问权限的inline函数(在某类的public:里写inline函数,这个inline函数是关于某类的数据成员的读写)。而类与类之间的或类与某非成员函数之间的复杂操作我们可以像inline函数那样直接跳到目标(成员)函数把它给展开了来运行,这样就省得什么解析,打包等一系列耗时的操作,这是我的理解。这样friend就派上了用场! - 任何类都可以将其他类或者函数指定为朋友(friend),如下图所示:
class Triangular{
friend int operator*(const Triangular_iterator &rhs);
//...
};
class Triangular_iterator{
friend int operator*(const Triangular_iterator &rhs);
//...
};
在某个类里将非成员函数声明为friend,该非成员函数就可以访问这个类的私有成员。这就是friend的作用。例子里把operator*()这个非成员函数在两个类里声明为了friend,它就可以直接访问Triangular类和Triangular_iterator类的私有成员了。(你可以说在类里声明为friend的非成员函数具有了和类成员函数相同的访问类私有成员的权限)
-
上面的声明可以出现在类定义的任何位置上,不论public:还是private:
-
当然重载函数声明为某个类的friend,必须所有的重载函数前都加上friend
-
所以,我们想让哪个非某类成员函数访问某类的私有成员,就在某类里
friend 返回类型 类名::成员函数名(参数表);
这样声明。不过这样声明你得先提供类名的那个类的定义让某类知道,否则会产生歧义和模糊。当然,如果那个非某类成员函数也不是其他类的成员函数,咋办啊?就是这样声明:friend 返回类型 函数名(参数表);
-
类与类之间也可以建立friend关系,比如class A与class B去建立关系,这样A类里的所有成员函数都成为了B类的friend,同理B类里的所有成员函数都成为A类的friend。举个例子:
class Triangular{
friend class Triangular_iterator;
//...
};
以此种形式来声明类之间的friend,就不需要在friend声明之前先显现class的定义(friend class那行那个类的定义)
- 如果某类定义了public里的成员函数,用到了其他类的成员函数的定义里了,就像这样
class Triangular{
public:
static int elem_size(){return _elems.size();}
static int max_elems(){return _max_elems;}
//...
};
inline void Triangular_iterator::
check_integrity()
{
if(_index>=Triangular::max_elems())
{
throw iterator_overflow();
}
if(_index>=Triangular::elems_size())
{
Triangular::gen_elements(_index+1);
}
}
那么我就不用在某类(Triangular类)里声明friend void Triangular_iterator::check_integrity();
(其他类的成员函数)从而让其他类的成员函数跟某类建立友谊。