在C++中我们可以將函数定义成类的友元函数,这样在函数中就可以访问类的私有成员。与函数相同,类也可以作为另一个类的友元类,在友元类中可以访问另外一个类的所有成员。
声明友元类的方法很简单,只需在类中写下如下语句:

friend class 类名;

接下来我们看一个案例,假如我们需要设计一个模拟电视机和遥控器的程序,代码如下。


#include <iostream>
using namespace std;

class TV
{
private:
    enum{on,off};
    enum{minvol,maxvol=100};
    enum{minchn,maxchn=40};
    bool on_off;
    int volume;
    int channel;
public:
    TV():on_off(off),volume(20),channel(3){};
    //打印属性
    void print_tv_info()
    {
        cout<<"on_off:"<<on_off<<endl;
        cout<<"volume:"<<volume<<endl;
        cout<<"channel:"<<channel<<endl;
    }
    //此处將TVController类声明为TV类的友元类
    friend class TVController;
};

class TVController
{
public:
    void set_status(TV& t){t.on_off = (t.on_off == t.on ? t.off : t.on);}
    bool volume_up(TV& t);
    bool volume_down(TV& t);
    bool channel_up(TV& t);
    bool channel_down(TV& t);
};
//TVController 函数定义
bool TVController::volume_up(TV& t)
{
    if(t.volume < t.maxvol)
    {
        t.volume++;
        return true;
    }
    return false;
}
bool TVController::volume_down(TV& t)
{
    if(t.volume > t.minvol)
    {
            t.volume--;
            return true;
    }
    return false;
}
bool TVController::channel_up(TV& t)
{
    if(t.channel < t.maxchn)
    {
        t.channel ++;
        return true;
    }
    return false;
}
bool TVController::channel_down(TV& t)
{
    if(t.channel > t.minchn)
    {
        t.channel --;
        return true;
    }
    return false;
}
int main(int argc,char* argv[]) {
    TV mytv;
    TVController ctl;
    ctl.set_status(mytv);
    ctl.volume_down(mytv);
    ctl.channel_up(mytv);
    mytv.print_tv_info();

    return 0;
}

我们定义了一个TV类和TVController分别表示电视机和遥控器。在电视机类有一些常用的属性,如:开关、频道、音量。我们分别用on_off、volume、channel变量表示;在遥控器类(TVController)中我们声明了以下方法来控制电视类:

    //开关电视机
    void set_status(TV& t){t.on_off = (t.on_off == t.on ? t.off : t.on);}
    //增大音量
    bool volume_up(TV& t);
    //减小音量
    bool volume_down(TV& t);
    //加频道
    bool channel_up(TV& t);
    //减频道
    bool channel_down(TV& t);

在这些方法中我们都需要访问TV类的成员变量,有两种方法,第一种是把TV类的成员变量都声明为public,但是这种做法显然不符合面向对象编程理念的。另一种是为每个属性增加set,get方法(例如:set_channel,get_channel),TVController类中对TV类的属性访问比较频繁,这样做代码会显得特别冗余,逻辑也不直观。
这时我们就需要將TVController类声明为TV类的友元类,具体做法是在TV类的声明中添加友元类的声明语句:

friend class TVController;

在main函数中我们定义TV类的对象mytv初始值为{on_off:1,volume:20,channel:5}和TVController 类的对象ctl,通过ctl对象的方法改变mytv对象的属性值。
执行程序输出:

on_off:0
volume:19
channel:4