zoukankan      html  css  js  c++  java
  • C++友元详解

    1.什么是友元
    在一个类A中,将类B声明为友元类,则类B可以访问类A的私有成员和保护成员。另外,也可以将函数声明为友元函数。

    2.什么时候用到友元
    若不同的类之间某些共享数据成员,可以使用友元,简化类的设计。

    3.友元类
    友元类的声明:friend class 类名
    示例如下:
    对于电视和遥控器来说,都共享频道数据成员和开关操作,这时可以将遥控器声明为电视的友元类,则遥控器可以直接访问电视的数据成员,且一个遥控器可以控制多台电视,这则例子很好的体现了友元的特点。

    tv.h

    #ifndef TV_H_
    #define TV_H_
    class Tv
    {
    public :
        friend class Remote;
        enum State{off,on};
    
        Tv(int s=off,int mc=125):state(s),maxchannel(mc),channel(2){}
    
        void onoff(){state=(state==on)?off:on;}
        void chanup();
        void chandown();
        void settings() const;
    private:
        int state;
        int maxchannel;
        int channel;
    };
    class Remote{
    public:
        Remote(){};
        void onoff(Tv &t){t.onoff();};
        void chanup(Tv &t){t.chanup();};
        void chandown(Tv &t){t.chandown();};
        void set_chan(Tv &t,int c){t.channel=c;};
    };

    tv.cpp

    #include<iostream>
    #include "tv.h"
    void Tv::chanup()
    {
        if(channel<maxchannel){
            channel++;
        }
        else{
            channel = 1;
        }
    }
    void Tv::chandown()
    {
        if(channel>1){
            channel--;
        }
        else{
            channel = maxchannel;
        }
    }
    void Tv::settings() const
    {
        using std::cout;
        using std::endl;
        cout<<"Tv is "<<(state==on?"on":"off")<<endl;
        if(state==on)
        {
            cout<<"channel:"<<channel<<endl;    
        }
    }

    use_tv.cpp 可使用同一个遥控器控制多台不同的电视

    #include<iostream>
    #include "tv.h"
    int main()
    {
        using std::cout;
        using std::endl;
        Tv s42;
        cout<<"Initing Tv s42......"<<endl;
        s42.settings();
        s42.onoff();
        s42.chanup();
        cout<<"adjusted Tv s42....."<<endl;
        s42.settings();
    
        Remote control;
        control.set_chan(s42,10);
        control.volup(s42);
        cout<<"settings after using remote......"<<endl;
        s42.settings();
        getchar();
        return 0;
    }

    示例可以看出,若不使用友元,则必须将Tv类的私有部分设置为共有的,或者创建一个大型类来包含电视和遥控器。这种解决方法也无法反应,一个遥控器可以用于多台电视。

    4.友元函数
    从上例可以看出,Remote类只有set_chan方法使用到了Tv类的私有成员,因此我们可以让Remote::set_chan()成为Tv类的友元函数,而不必让整个类成为友元

    tvfm.h

    #ifndef TV_H_
    #define TV_H_
    class Tv;
    class Remote{
    public :
        enum State{off,on};
    private:
        int mode;
    public:
        Remote(){};
        void onoff(Tv &t);
        void chanup(Tv &t);
        void chandown(Tv &t);
        void set_chan(Tv &t,int c);
    };
    class Tv
    {
    public :
        friend void Remote::set_chan(Tv &t,int c);
        enum State{off,on};
    
        Tv(int s=off,int mc=125):state(s),maxchannel(mc),channel(2){}
    
        void onoff(){state=(state==on)?off:on;}
        void chanup();
        void chandown();
        void settings() const;
    private:
        int state;
        int maxchannel;
        int channel;
    };
    
    inline void Remote::onoff(Tv &t){t.onoff();}
    inline void Remote::chanup(Tv &t){t.chanup();}
    inline void Remote::chandown(Tv &t){t.chandown();}
    inline void Remote::set_chan(Tv &t,int c){t.channel=c;}
    #endif

    5.共同的友元
    多个类需要访问同一个函数,则可以在这些类中将这个函数声明为友元函数。例如:有一个计数器函数counter,两个类A和B同时调用这个函数,则可以在类A和B中将函数counter声明为友元函数。

    void counter()
    {
        //....
    }
    class A
    {
        friend int counter();
    }
    class B
    {
        friend int counter();
    }

    6.使用友元类时注意:
    1) 友元关系不能被继承。
    2)友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元。
    3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元

    参考资料:《C++ Primer.Plus》 pp.602-610

  • 相关阅读:
    layui timeline使用
    Java随机数使用
    Matlab信号处理工具箱函数
    高斯白噪声(white Gaussian noise,WGN)
    概率分布之间的距离度量以及python实现
    Wasserstein距离 和 Lipschitz连续
    线性分式变换(linear fractional transformation)
    算法的时间复杂度和空间复杂度-总结
    随机森林(Random Forest,简称RF)
    增强学习与马尔科夫决策过程
  • 原文地址:https://www.cnblogs.com/shijingjing07/p/5522720.html
Copyright © 2011-2022 走看看