1、类可以允许其他类、类的成员函数或者外部函数访问它的非公有成员,方法是令其他类或者函数成为它的友元。
1.1、如果类想把一个类或者外部函数作为它的友元,只需要增加一条以friend关键字开始的类或者函数声明语句即可。
1.2、如果想把其他类的成员函数作为它的友元,除了friend关键字外,函数名之前还需要明确指出该成员函数所属的类。(代码见底部)
2、友元声明只能出现在类定义的内部,但是在类内出现的具体位置不限。友元不是类成员也不受它所在区域访问控制级别的约束。
3、友元函数能定义在类的内部,这样的函数是隐式内联的。
4、友元的声明仅仅指定了访问的权限,而非一个通常意义上的函数声明,所以需要在友元声明之外再专门对函数进行一次声明,而后在调用它。即使我们仅仅是用声明友元的类的成员函数调用该友元函数,它也必须是被声明过的。
这里有两种情况:(1)当友元函数定义在类的外部时,这个定义也就声明了该函数,但是还是建议单独声明该函数并将其与类的定义放置在同一个头文件中(类的外部),这样当我们要使用该类以及友元函数时,只需添加该头文件即可。(2)当友元函数的定义在类的内部时,由于没有了外部定义产生的声明,所以需要单独声明,同样,最好声明在类定义所在的头文件中。
一些编译器并没有强制要求必须在类的外部进行要作为友元的函数的声明,不过最好在任何情况下都做出该函数的声明。
5、友元关系不存在传递性。
7、如果一个类想把一组重载函数声明成它的友元,它需要对这组函数中的每一个分别声明。
6、类和非成员函数的声明不必出现在他们的友元声明之前(注意这里不包括类的成员函数,也就是说类的成员函数的声明需要出现在它的友元声明之前)。当一个名字第一次出现在一个友元声明中时,我们隐式的假定该名字在当前作用域中是可见的。然而友元本身不一定真的声明在当前作用域中。
把其他类的成员函数作为友元:
//不可随意改变程序的有关类和函数的声明以及定义的顺序
#include <iostream>
using namespace std;
#include <string>
class screen;//声明screen类,否则第17行会出现找不到screen
class window_mgr//先定义包含友元成员函数声明的类
{
public:
window_mgr(int aa, string bb) :a(aa), b(bb) {}
void print()
{
cout << "window_mgr::a=" << a << endl;
cout << "window_mgr::b=" << b << endl;
}
void clear(screen& sc);//clear函数的声明(将要被作为class类的友元)
private:
int a;
string b;
};
class screen
{
friend void window_mgr::clear(screen& sc);//clear的友元声明
public:
screen(int aa, string bb) :c(aa), d(bb) {}
void print()
{
cout << "screen::c=" << c << endl;
cout << "screen::d=" << d << endl;
}
private:
int c;
string d;
};
void window_mgr::clear(screen& sc)//clear函数的定义
{
//作为普通函数的调用来改变对象的数据
sc.c = 0;
sc.d = " ";
//作为成员函数
a = 0;
b = " ";
}
int main()
{
screen scr(8, "hello");
window_mgr wi(5, "world");
scr.print();
wi.print();
cout << endl;
wi.clear(scr);//调用
scr.print();
wi.print();
}