1、友元
友元分为友元类和友元函数。有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数;还可以把一个类作为另一个类的友元,这叫友元类。
(1)、友元类
友元类可以使用原始类的方法,这在一定程度上破坏了类封装的密封性。
友元类的公有方法称为原始类的私有方法;如下面的Remote类是Tv类的友元类,则Remote类中的公有方法volup()等成为了Tv类的私有方法。
class Tv
{
public:
friend class Remote;//Remote类成为了Tv类的友元类
void onoff(){state=(state==On)?Off:On;}
bool volup();
.....
};
class Remote
{
public:
void onoff(Tv & t){t.onoff();}//使用Tv类的方法
bool volup(Tv & t){return t.volup();}//使用Tv类的方法
.....
};
在相应的.cpp中只需给出Tv类的实现方法,
#include<iostream>
#include"tv.h"
bool Tv::volup()
{
if(volume<MaxVol)
{
volume++;
return true;
}
else
return false;
}
......
则在使用时,Tv和Remote类的对象都可以实现对电视的控制;
int main()
{
Tv tv1;
tv1.volup();//电视用自己的方法控制音量
Remote remoteControl;
remoteControl.volup(tv1);//使用友元类控制音量
......
}
(2)友元函数
当仅需要使特定类的某个类成员称为另一个类的友元时,使用友元函数。但是这时需要注意排列各种声明和定义的顺序。
如果要使Remote类中的某个成员函数称为Tv类的友元函数,要使用前向声明。排列次序为:
class Tv;//前向声明
class Remote{....};
class Tv{.....};
这样做的原因是:在编译器在Tv类的声明中看到Remote的一个方法被声明为Tv类的友元函数之前,需要先看到Remote类的声明和作为友元函数的成员函数的声明。
现在将Remote类中的set_channel()作为Tv类的友元函数,可以这样实现:
//文件:tv_remote.h
calss Tv;
class Remote
{
public:
enum State{On,Off};
...
void set_channel(Tv & t,int ch);//set_channel左右友元函数需要先声明
private:
int mode;
};
class Tv
{
public:
friend void Remote::set_channel(Tv & t,int ch);//设定该函数为友元函数
.....
};
同样被设为友元函数的成员函数set_channel()成为了Tv 类的私有成员;
(3)共同友元
当函数需要访问两个类的私有数据时,可以将韩式作为两个类的友元,即共同友元;
class A;
class B
{
friend void func(A & a,const B & b);
friend void func(const A & a,B & b);
....
};
class A
{
friend void func(A & a,const B & b);
friend void func(const A & a,B & b);
....
};
inline friend void func(A & a,const B & b)
{
...
}
inline friend void func(const A & a,B & b)
{
....
}
如此,函数func称为类A,类B的共同友元。