14.11 c++ 友元

14.11 友元

类的主要特点之一是数据隐藏,即类的私有成员无法在类的外部(作用域之外)访问。但是,有时候需要在类的外部访问类的私有成员,怎么办?

解决方法是使用友元函数,友元函数是一种特权函数,c++允许这个特权函数访问私有成员。这一点从现实生活中也可以很好的理解:比如你的家,有客厅,有你的卧室,那么你的客厅是Public的,所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以运行你的闺密好基友进去。程序员也可以把一个全局函数、某个类中的成员函数、甚至整个类声明为友元。

14.11.1 友元的语法

使用friend关键字声明友元。

friend关键字只出现在声明处,一个函数或者类作为了另一个类的友元 那么这个函数或类就可以直接访问 另一个类的私有数据。

友元 重要用在运算符重载上。

14.11.2 普通全局函数作为类的友元

#include <string>
using namespace std;
class Room
{
	friend void visting01(Room &room);
private:
	string bedRoom;//卧室
public:
	string setingRoom;//客厅
public:
	Room(string bedRoom,string setingRoom)
	{
		this->bedRoom = bedRoom;
		this->setingRoom = setingRoom;
	}
};

//普通全局函数
void visiting01(Room &room)
{
    cout<<"访问了"<<room.setingRoom<<endl;
    cout<<"访问了"<<room.bedRoom<<endl;
}
int main()
{
	Room room("卧室","客厅");
    visiting01(room);
    return 0
}

14.11.3 类的某个成员函数作为另一个类的友元

class Room;//向前声明 只能说明类名称
class goodGay
{
public:
    void visiting01(Room &room);
    void visiting02(Room &room);
};
class Room
{
    friend void goodGay::visiting02(Room &room);
private:
    string bedRoom;//卧室
public:
    string setingRoom;//客厅
public:
    Room(string bedRoom, string setingRoom)
    {
        this->bedRoom=bedRoom;
        this->setingRoom=setingRoom;
    }
};
void goodGay::visiting01(Room &room)
{
    cout<<"访问了"<<room.setingRoom<<endl;
    //cout<<"访问了"<<room.bedRoom<<endl;
}
void goodGay::visiting02(Room &room)
{
	cout<<"好基友张三访问了"<<room.setingRoom<<endl;
    cout<<"好基友张三访问了"<<room.bedRoom<<endl;
}
int main()
{
    Room room("卧室","客厅");
    goodGay ob;
    ob.visiting01(room);
    ob.visiting02(room);
    return 0;
}

14.11.4 整个类作为另一个类的友元

这个类的所有成员函数都可以访问另一个类的私有数据。

class Room;
class goodGay
{
public:
    void visiting01(Room &room);
    void visiting02(Room &room);
};
class Room
{
    friend class goodGay;
private:
    string bedRoom;//卧室
public:
    string setingRoom;//客厅
public:
    Room(string bedRoom, string setingRoom)
    {
        this->bedRoom=bedRoom;
        this->setingRoom=setingRoom;
    }
};
void goodGay::visiting01(Room &room)
{
    cout<<"访问了"<<room.setingRoom<<endl;
    cout<<"访问了"<<room.bedRoom<<endl;
}
void goodGay::visiting02(Room &room)
{
	cout<<"好基友张三访问了"<<room.setingRoom<<endl;
    cout<<"好基友张三访问了"<<room.bedRoom<<endl;
}
int main()
{
    Room room("卧室","客厅");
    goodGay ob;
    ob.visiting01(room);
    ob.visiting02(room);
    return 0;
}

14.11.5 友元的注意事项

  1. 友元关系不能被继承
  2. 友元关系是单向的,类A是类B的朋友,但类B不一定是类A的朋友。
  3. 友元关系不具有传递性。类B是类A的朋友,类C是类B的朋友,但类C不一定是类A的朋友。

14.11.6 友元的案例(遥控器的类)

请编写电视机类,电视机有开机和关机状态,有音量,有频道,提供音量操作的方法,频道操作的方法。由于电视机只能逐一调整频道,不能指定频道,增加遥控类,遥控类除了拥有电视机已有的功能,在增加根据输入调台功能。

提示:遥控器可作为电视机类的友元类

#include <iostream>
using namespace std;
class TV;
//遥控器的类作为TV的友元
class Remote
{
private:
    TV *p;
public:
    Remote(TV *p)
    {
        this->p = p;
    }
    void offOrOn(void);
    void upVolume(void);
    void downVolume(void);
    void upChannel(void);
    void downChannel(void);
    void showTv(void);
    void setChannel(int channel);
};
class TV
{
    friend class Remote;
    enum{OFF,ON};
    enum{minVol, maxVol=10};
    enum{minChan,maxChan=25};
private:
    int state;
    int volume;
    int channel;
public:
    TV()
    {
        state = OFF;
        volume = minVol;
        channel = minChan;
    }

    void offOrOn(void);
    void upVolume(void);
    void downVolume(void);
    void upChannel(void);
    void downChannel(void);
    void showTv(void);

};
int main()
{
    TV tv;
    Remote re(&tv);
    re.offOrOn();
    re.upVolume();
    re.upVolume();
    re.setChannel(10);
    re.showTv();
    return 0;
}
void TV::offOrOn()
{
    state = (state==OFF?ON:OFF);
}
void TV::upVolume()
{
    if(volume == maxVol)
    {
        cout<<"音量已经最大"<<endl;
        return;
    }
    volume++;
}
void TV::downVolume()
{
    if(volume == minVol)
    {
        cout<<"音量已经最小"<<endl;
        return;
    }
    volume--;
}
void TV::upChannel()
{
    if(channel == maxChan)
    {
        cout<<"频道已经最大"<<endl;
        return;
    }
    channel++;
}
void TV::downChannel()
{
    if(channel == minChan)
    {
        cout<<"频道已经最小"<<endl;
        return;
    }
    channel--;
}
void TV::showTv()
{
    cout<<"当前电视机的状态:"<<(state==OFF?"关":"开")<<endl;
    cout<<"当前电视机的音量:"<<volume<<endl;
    cout<<"当前电视机的频道:"<<channel<<endl;
}
void Remote::offOrOn()
{
    p->offOrOn();
}
void Remote::upVolume()
{
    p->upVolume();
}
void Remote::downVolume()
{
    p->downVolume();
}
void Remote::upChannel()
{
    p->upChannel();
}
void Remote::downChannel()
{
    p->downChannel();
}
void Remote::showTv()
{
    p->showTv();
}
void Remote::setChannel(int channel)
{
    if(channel>=TV::minChan && channel<=TV::maxChan)
    {
        p->channel = channel;
    }
    else {
        cout<<"频道"<<channel<<"不在有效范围内"<<endl;
    }
}

14.11.7 设计动态数组类案例

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值