C++进阶--友元

参考资料--《C++ Primer Plus 第六版》

1.友元函数

区别于普通非成员函数,友元函数是一种特殊的非成员函数,它可以访问类的私有成员;

友元函数访问权限与成员函数相同,都可以访问私有、公有数据,因此友元函数相当于类的扩展接口

示例:

//声明,声明要放在类的声明中
friend Time operator*(double m, const Time & t);

//定义
Time operator*(double mult, const Time & t)
{
    Time result;
    long totalminutes = hours * mult * 60 + minutes * mult;
    result.hours = totalminutes / 60;
    result.minutes = totalminutes % 60;
    return result;
}

//调用
A = operator*(2.75, B);

其中,友元函数声明要放在类的声明中,在其原型上加上 friend 关键字;

其次,在定义时不要使用类限定符(Time::),且不要再定义中使用 friend 关键字;

2.友元类

在类中除了可以声明友元函数外,还可以声明友元类,此时友元类的所有方法都都可以访问原始类的私有成员和保护成员;

下面语句使Remote成为友元类:

friend class Remote;   // Remote can access Tv private parts

友元声明可以放在公有、私有、保护的任何地方,位置无关紧要;

如下示例,因为Remote类中会用到Tv类的方法,所以编译器必须先知道Tv类,所以要先定义Tv类:

// tv.h -- Tv and Remote classes
#ifndef TV_H_
#define TV_H_

class Tv
{
public:
    friend class Remote;   // Remote can access Tv private parts
    enum {Off, On};
    enum {MinVal,MaxVal = 20};
    enum {Antenna, Cable};
    enum {TV, DVD};

    Tv(int s = Off, int mc = 125) : state(s), volume(5),
        maxchannel(mc), channel(2), mode(Cable), input(TV) {}
    void onoff() {state = (state == On)? Off : On;}
    bool ison() const {return state == On;}
    bool volup();
    bool voldown();
    void chanup();
    void chandown();
    void set_mode() {mode = (mode == Antenna)? Cable : Antenna;}
    void set_input() {input = (input == TV)? DVD : TV;}
    void settings() const; // display all settings
private:
    int state;             // on or off
    int volume;            // assumed to be digitized
    int maxchannel;        // maximum number of channels
    int channel;           // current channel setting
    int mode;              // broadcast or cable
    int input;             // TV or DVD
};

class Remote
{
private:
    int mode;              // controls TV or DVD
public:
    Remote(int m = Tv::TV) : mode(m) {}
    bool volup(Tv & t) { return t.volup();}
    bool voldown(Tv & t) { return t.voldown();}
    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;}
    void set_mode(Tv & t) {t.set_mode();}
    void set_input(Tv & t) {t.set_input();}
};
#endif

可以看到除了构造函数,Romote方法都将Tv对象引用作为参数;且所有的方法都是使用Tv的方法,所以这里只需要定义Tv的方法即可,如下所示:

// tv.cpp -- methods for the Tv class (Remote methods are inline)
#include <iostream>
#include "tv.h"

bool Tv::volup()
{
    if (volume < MaxVal)
    {
        volume++;
        return true;
    }
    else
        return false;
}
bool Tv::voldown()
{
    if (volume > MinVal)
    {
        volume--;
        return true;
    }
    else
        return false;
}

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 == Off? "Off" : "On") << endl;
    if (state == On)
    {
        cout << "Volume setting = " << volume << endl;
        cout << "Channel setting = " << channel << endl;
        cout << "Mode = "
            << (mode == Antenna? "antenna" : "cable") << endl;
        cout << "Input = "
            << (input == TV? "TV" : "DVD") << endl;
    }
}

测试程序:

//use_tv.cpp -- using the Tv and Remote classes
#include <iostream>
#include "tv.h"

int main()
{
    using std::cout;
    Tv s42;
    cout << "Initial settings for 42\" TV:\n";
    s42.settings();
    s42.onoff();
    s42.chanup();
    cout << "\nAdjusted settings for 42\" TV:\n";
    s42.settings();

    Remote grey;

    grey.set_chan(s42, 10);
    grey.volup(s42);
    grey.volup(s42);
    cout << "\n42\" settings after using remote:\n";
    s42.settings();

    Tv s58(Tv::On);
    s58.set_mode();
    grey.set_chan(s58,28);
    cout << "\n58\" settings:\n";
    s58.settings();
    // std::cin.get();
    return 0; 
}

3.友元成员函数--略

4.共同的友元

第一种是让类彼此成为对方的友元,比如让Remote是Tv的友元,Tv也是Remote的友元;

class Tv
{
friend class Remote; 

public:
    void buzz(Remote & r);
    ...
};

class Remote
{
friend class Tv;

public:
    void Bool volup(Tv & t) { t.volup }

};

inline void Tv::buzz(Remote & r)
{
    ...
}

第二种是一个函数分别是两个类的友元,可分别访问两个类的私有数据,如下:

class Analyzer; //forward declaration

class Probe
{
    friend void sync(Analyzer & a, const Probe & p); //sync a to p
    friend void sync(Probe & p, const Analyzer & a); //sync p to a
    ...
};

class Analyzer 
{
    friend void sync(Analyzer & a, const Probe & p); //sync a to p
    friend void sync(Probe & p, const Analyzer & a); //sync p to a
    ...
};

//define the friend function
inline void sync(Analyzer & a, const Probe & p)
{
    ...
}

inline void sync(Probe & p, const Analyzer & a)
{
    ...
}

这里的前向声明 class Analyzer ,使编译器看到 Probe 类声明中的友元声明时,知道Analyzer是一种类型;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值