对于希望部分开放访问权限的类,友元是必须的
例如A类的private部分只让B方法访问并控制,而拒绝C方法的访问
通常情况下我们可以把B写成A类的成员函数
但是如果我们想要B函数成为一个接口,即参数不仅限于一个类对象,那么我们想要特化的这个B函数,应当拥有多个类对象的访问权,此时就需要用友元
友元可以是类,也可以是函数(成员函数或者全局函数都可以)
class D; class A { friend void clearA(A& a); friend class D; int m_B; } void clearA(A& a) { a.m_B=0; } class D { void accessA(A& a); }
这样做的话,全局函数clearA和class D的成员函数可以访问并修改A类的所有成员变量和成员函数
一个友元的声明必须在类的内部,在函数前加一条friend开头的关键字
但是这个友元声明不应该是友元函数本体的声明,友元并不是类成员,其作用仅仅只是当某个函数试图访问类对象的时候的权限校验,这一切都是编译器在记录并控制访问权限(有的编译器将不强制执行这个原则,而允许将友元声明当做函数声明,这样就破坏了函数的命名空间的规则,但是我们最好还是按标准来)
在友元函数的函数本体声明之前,调用该函数是非法的
class A { friend void f(); A(){ f();} //非法操作,f尚未声明 void g(); void h(); } void g(){ f();} //非法,f函数尚未声明 void f(); //声明f函数 void h(){ f();} //合法,f函数已经声明 void f(){ return 0;} //定义f函数
一般来说,友元函数的函数本体声明最好在类之前,但是有的编译器也支持无需类外的函数声明
对于一般函数或者整个类,友元的声明比较简单,但是如果某个类要将另一个类的某个成员函数作为友元的话,会稍复杂
例如,我只希望B类的成员函数clearA作为A类的友元,那么我需要
1.声明A类
2.声明B类,并声明B类成员函数clearA(在此之前需要声明A类的原因是clearA函数将包含A类型的参数,需要可见的声明)
3.定义A类,并将B类的clearA函数声明为友元函数(在此之前需要声明B类的是因为友元声明需要有外部声明)
4.定义B类成员函数clearA(在此之前需要定义A类的原因是clearA包含了对A类对象的操作,而对象需要有定义)
完class A; //声明class A class B { void clearA(A& a);//声明clearA函数 }; class A //定义classA并将B类的clearA声明友元 { friend B::void clearA (A& a); int m_C; } B::void clearA(A& a) //定义clearA对于对象a的操作 { a.m_C=0; }