C++:友元

来源:互联网 发布:淘宝闲鱼拍卖流程 编辑:程序博客网 时间:2024/04/28 17:43

C++:友元

标签(空格分隔): c++


  • C友元
  • 友元类
  • 友元成员函数
  • 共同的友元

类并非只能拥有友元函数,也可以将类作为友元。在这种情况下,友元类的所有方法都可以访问原始类的私有成员和保护成员。另外,也可以做更严格的限制,只有将特定成员函数指定为另一个类的友元。1

友元类


这里我们以遥控器与电视机的关系为例,电视机与遥控器有关系,但是其关系不是继承的is-a关系,同样也不可能是包含has-a关系。所以这里提出了一种新的联系方式:友元类

现在我们设计一款电视,这个电视不保留除开机键外的一切按键,所有一切都由遥控器控制,也就是要求遥控器能够访问电视的私有成员,遥控器又作为电视机的用户接口。

#ifndef primer_tv_h#define primer_tv_h#include<iostream>class Tv{private:    enum {LESS=0,LARGE=100,CHANNEL=64};//音量范围0-100,频道数量255    bool _power;//电源接通状态    bool _switch;//待机切换状态    int _voice;//声音    int _channel;//频道    void switch_(){        if(_power){//只有电源接通状况下才可以切换待机状态            _switch = !_switch;            if(_switch) show();        }    }    void voiceUp(){        if(_switch){//调大音量            if(_voice < LARGE) _voice++;            show();        }    }    void voiceDown(){        if(_switch){//调小音量            if(_voice > LESS) _voice--;            show();        }    }    void channelPiror(){        if(_switch){//向前换台            _channel = (_channel-1)%LARGE;            show();        }    }    void channelNext(){        if(_switch){//向后换台            _channel = (_channel+1)%LARGE;            show();        }    }    void channel(int c){//切换到某一频道        if(c<0)            _channel = 0;        else if(c>CHANNEL)            _channel = CHANNEL;        else            _channel = c;        show();    }    void show(){//显示节目状态        std::cout<<"~~~当前电视频道:"<<_channel<<" ,电视音量:"<<_voice<<"~~~"<<endl;    }public:    friend class Remote;//声明友元遥控器    Tv(){        _power = false;        _switch = false;        _voice = 20;        _channel = 0;    }    ~Tv(){}    void powerOn(){        _power = true;    }    void powerOff(){        _switch = false;        _power = false;    }};class Remote{private:    Tv *_tv;public:    Remote(Tv *tv):_tv(tv){};    ~Remote(){}    void switch_(){_tv->switch_();}    void voiceUp(){_tv->voiceUp();}    void voiceDown(){_tv->voiceDown();}    void channelPiror(){_tv->channelPiror();}    void channelNext(){_tv->channelNext();}    void channel(int c){_tv->channel(c);}};#endif

现在我们来测试一下

#include"stdafx.h"#include "tv.h"int main(int argc, const char * argv[]) {    cout<<"买了一个小米的新电视"<<endl;    Tv *mi = new Tv();    cout<<"打开箱子一看发现了一台遥控器"<<endl;    Remote mi_r(mi);    cout<<"我想看电视于是使用遥控器打开开关"<<endl;    mi_r.switch_();    cout<<"发现电视并没有什么反应,仔细检查后发现一激动忘记接电源了,"<<"现在接通电源"<<endl;    mi->powerOn();    cout<<"再用遥控器打开"<<endl;    mi_r.switch_();    cout<<"果然看到节目了,累了一天打算看新闻联播放松放松,由于知道13频道是新闻频道,所以直接在遥控器上输入13"<<endl;    mi_r.channel(133);    cout<<"为什么是64频道,仔细一看是自己多按了一个3,于是自己小心的又按了一遍13"<<endl;    mi_r.channel(13);    cout<<"啊,看到新闻联播后突然很困,就想把声音关小一点"<<endl        <<"然后我就一直一直按减小音量键"<<endl;    for(int i=0;i<30;i++){        mi_r.voiceDown();    }    cout<<"看来我确实是太困了,都按了这么多下按键,算了待机睡觉吧"<<endl;    mi_r.switch_();    cout<<"我看看待机后按键有没有用"<<endl;    mi_r.channelPiror();    mi_r.channelNext();    mi_r.voiceDown();    cout<<"按了三个按键都没反应,看来真待机了,为了省电我要关闭电源键"<<endl;    mi->powerOff();    cout<<"可以安心睡觉了"<<endl;    return 0;}

从这个例子中我们可以看出,友元声明可以位于公有、私有或者保护部分,其所在的位置无关紧要。由于我们在Remote类中使用Tv类,所以必须在Remote类前声明class Tv

友元成员函数


假如我们现在有一台老式的电视,这台电视提供了许多公有的按键。于是我们的遥控器访问这些方法的时候并不需要真正的友元,唯一需要成为友元方法的是channel方法,因为电视机上不可能会给你提供数字按键

class Tv{private:    ...    void channel(int c);//切换到某一频道    void show();//显示节目状态public:    ...    void voiceUp();    void voiceDown();    void channelPiror();    void channelNext();};

那么我们仅仅需要让Remote.channel(int c)的方法成为Tv的友元:

class Tv{    ...    friend void Remote::channel(int c);};

然而,要使编译器能够处理这条指令,它必须知道Remote的定义:

class Remote;class Tv{    ...    friend void Remote::channel(int c);};

共同的友元


最简单的例子,我们的遥控器不仅仅只能控制一台电视机的。所以我们可以给两台Tv声明同一个遥控器作为友元类。


  1. Stephen Prata.C++ Primer Plus 6th.人民邮电出版社.2015.3 602-611 ↩
0 0
原创粉丝点击