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

posted on 2016-05-24 11:10  迪米特  阅读(1083)  评论(0编辑  收藏  举报

导航