友元简介:友元函数,友元类和友元成员函数

友元简介:
C ++为了保证类的封装性,使私有部分和保护部分对外不可见,公有部分提供唯一的访问途径。(基类的保护部分在 public,protected方式的派生类中,也对外提供访问途径,在派生类中访问权限同公有部分)。
但这样的限制太严格,以至于不适合特定的编程,因此,C ++提供了另一种形式的访问权限,即友元。使得可以访问友元所在类的私有部分和保护部分。友元与位于类的 public, private,protected的位置无关,均可访问所在类的私有部分和保护部分。
友元在一定程度上破坏了类的封装性,但同时也是类的接口操作更加灵活。
友元分为 3中:
1.友元函数
2.友元类
3.友元成员函数

1.友元函数
可以将单独一函数作为一个类的友元函数,使这个函数具有访问 后者私有成员和保护成员的能力。
例子:
class Tv
{
    private:
        int channel;
        int mode;
    protected:
        int vol;         
    public:
        ....
       friend void settings(int c, Tv& t)  { t.channel = c;   t.mode = c;} //直接访问对类对象的 私有成员和保护成员
}

2.友元类
将一个类声明为另一个类的友元,这样作为友元的类 就可以访问 后者的私有成员和保护成员了。(无论友元类声明在后一个类的公有部分还是 私有部分,其所在位置无关紧要)
使用场合:如 电视机与遥控的关系。不是has -a 的关系,因为 一台遥控可以控制多个电视。同时更不是 a kind of的关系。但是 遥控可以改变 电视机的状态,此种情况用友元来实现,更合适,即让遥控类作为电视机类的友元,可以更改其私有成员。

例子:
    class Tv
    { 
    private:
        int channel;
        int mode;
    protected:
        int vol;         
    public:
        void set_mode();
        friend class Remote;  
    }
    class Remote
    {
    private:
        int mode;
    public:
        void set_mode(Tv &t)   { t.set_mode(); }  //#1
        void set_vol(int c, Tv&t)    {t.vol= c;}// #2    访问 类的保护成员
        void set_chan(int c, Tv&t)      {t.channel = c;} // #3   访问 类的私有成员
    }


3.友元成员函数
亦可以将一个类的成员函数作为另一个类的友元函数,仅使类的这个成员函数具有访问后者私有成员和保护成员的能力,其他类成员无这个能力。
如上例中,
class Remote
{
   ...
  public:
      void set_mode(Tv &t)   { t.set_mode(); }  //#1
  .....
}


# 1依然为使用Tv类的公有接口来实现功能。 # 2,# 3直接访问 私有部分和保护部分,因此可只将 # 2,# 3的类成员函数声明为Tv类的友元,Remote类的其他成员 只用通过公有接口来访问Tv类。
这样做两个注意项:
1.前向声明的使用。
2.类定义置后。(保证当一个类的定义中 使用另一个类的方法时,所用的方法在此定义之前,已声明)。
需小心排列各种声明和定义的顺序。

例:
class Tv;  //Note 1:前向声明    因为Note 2 处 用到Tv &t,需告诉编译器,此处Tv 为类
class Remote
{
private:
    int mode;
public:
    enum{Off, On};
    enum{MinVal, MaxVal = 20};
    enum{Antenna, Cable};
    enum{TV, VCR};
public:
    Remote(int m = TV):mode(m){}
    void onoff(Tv &t);  //Note 2:   error #1 {t.onff();}  因为在此之前未见到Tv 类的 onoff()成员函数,所以此定义需后置  
    void vol_up(Tv &t);  
    void vol_down(Tv &t);
    void channel_up(Tv &t);
    void channel_down(Tv &t);
    void set_mode(Tv &t);
    void set_input(Tv &t);
    void set_chan(Tv &t, int c);
};
class Tv
{
private:
    int state;
    int channel;
    int maxchannel;
    int mode;
    int input;
    int volume;
public:
    friend void Remote::set_chan(Tv &t,int c);// Note:3   声明 友元成员函数 
    enum{Off, On};
    enum{MinVal, MaxVal = 20};
    enum{Antenna, Cable};
    enum{TV, VCR};

    Tv(int s = Off, int mc = 100):state(s),maxchannel(mc),volume(5),
        input(TV),mode(Antenna),channel(1){}
    bool ison()const {return (state== On ? TRUE:FALSE);}
    void onoff() {state = (state == On ? Off:On);}
    void vol_up();
    void vol_down();
    void channel_up();
    void channel_down();
    void set_mode() {mode = (mode == Antenna ? Cable:Antenna);}
    void set_input() {input = (input == TV ? VCR : TV);}
    void settings();
};
void Tv::vol_up()
{
    if (volume == MaxVal)
    {
        volume = MinVal;
    }
    else
        volume++;
}
void Tv::vol_down()
{
    if (volume == MinVal)
    {
        volume = MaxVal;
    }
    else
        volume--;
}
void Tv::channel_up()
{
    if (channel == maxchannel)
    {
        channel = 1;
    }
    else
        channel++;
}
void Tv::channel_down()
{
    if (channel == 1)
    {
        channel = maxchannel;
    }
    else
        channel--;
}
void Tv::settings()
{
    cout<<"Tv is "<<(state== On ? "on":"off")<<endl;
    if (state == On)
    {
        cout<<"channel  volume      mode  input\n";
        cout<<setw(7)<<channel<<setw(8)<<volume
            <<setw(10)<<(mode== Antenna ?"Antenna":"cable")
            <<setw(7)<<(input== TV ? "TV":"Cable")<<endl;
    }    
}
inline void Remote::onoff(Tv&t) {t.onoff();} //Note 4:  Remote 类方法定义置于 Tv类方法声明之后
inline void Remote::vol_up(Tv&t) {t.vol_up();}
inline void Remote::vol_down(Tv&t) {t.vol_down();}
inline void Remote::channel_up(Tv&t) {t.channel_up();}
inline void Remote::channel_down(Tv&t) {t.channel_down();}
inline void Remote::set_mode(Tv&t) {t.set_mode();}
inline void Remote::set_input(Tv&t) {t.set_input();}
inline void Remote::set_chan(Tv&t, int c){t.channel= c;}
讨论此处使用的为
class Tv;
class Remote
{
}
class TV
{
}
的方法,能否交换次序?改为:
class Remote;
class Tv
{}
class Remote
{}
答案不能。 Tv 的声明有 friend void Remote::set_chan(Tv &t,int c); 而在此前未见到 Remote类的声明(即含有set_chan(Tv &t, int c); 这一成员函数)。因此,在Tv的类定义之前,需先见到Remote的类定义。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值