友元

4.5 友元

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

解决方法是使用友元函数,友元函数是一种特权函数,c++允许这个特权函数访问私有成员。这一点从现实生活中也可以很好的理解:

比如你的家,有客厅,有你的卧室,那么你的客厅是Public的,所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的闺蜜好基友进去。

程序员可以把一个全局函数、某个类中的成员函数、甚至整个类声明为友元。

4.5.1 友元语法

n friend关键字只出现在声明处

n 其他类、类成员函数、全局函数都可声明为友元

友元函数不是类的成员,不带this指针

n 友元函数可访问对象任意成员属性,包括私有属性

 

class Building;
//友元类
class MyFriend{
public:
    //友元成员函数
    void LookAtBedRoom(Building& building);
    void PlayInBedRoom(Building& building);
};
class Building{
    //全局函数做友元函数
    friend void CleanBedRoom(Building& building);
#if 0
    //成员函数做友元函数
    friend void MyFriend::LookAtBedRoom(Building& building);
    friend void MyFriend::PlayInBedRoom(Building& building);
#else    
    //友元类
    friend class MyFriend;
#endif
public:
    Building();
public:
    string mSittingRoom;
private:
    string mBedroom;
};

void MyFriend::LookAtBedRoom(Building& building){
    cout << "我的朋友参观" << building.mBedroom << endl;
}
void MyFriend::PlayInBedRoom(Building& building){
    cout << "我的朋友玩耍在" << building.mBedroom << endl;
}

//友元全局函数
void CleanBedRoom(Building& building){
    cout << "友元全局函数访问" << building.mBedroom << endl;
}

Building::Building(){
    this->mSittingRoom = "客厅";
    this->mBedroom = "卧室";
}

int main(){

    Building building;
    MyFriend myfriend;

    CleanBedRoom(building);
    myfriend.LookAtBedRoom(building);
    myfriend.PlayInBedRoom(building);

    system("pause");
    return EXIT_SUCCESS;
}

 

    [友元类注意]

1.友元关系不能被继承。

2.友元关系是单向的,类A是类B的朋友,但类B不一定是类A的朋友。

3.友元关系不具有传递性。类B是类A的朋友,类C是类B的朋友,但类C不一定是类A的朋友。

 

思考: c++是纯面向对象的吗?

如果一个类被声明为friend,意味着它不是这个类的成员函数,却可以修改这个类的私有成员,而且必须列在类的定义中,因此他是一个特权函数。c++不是完全的面向对象语言,而只是一个混合产品。增加friend关键字只是用来解决一些实际问题,这也说明这种语言是不纯的。毕竟c++设计的目的是为了实用性,而不是追求理想的抽象。

                                                       --- Thinking in C++

 

 

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

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

class Remote;

class Television{
    friend class Remote;
public:
    enum{ On,Off }; //电视状态
    enum{ minVol,maxVol = 100 }; //音量从0到100
    enum{ minChannel = 1,maxChannel = 255 }; //频道从1到255
    Television(){
        mState = Off;
        mVolume = minVol;
        mChannel = minChannel;
    }

    //打开电视机
    void OnOrOff(){
        this->mState = (this->mState == On ? Off : On);
    }
    //调高音量
    void VolumeUp(){
        if (this->mVolume >= maxVol){
            return;
        }
        this->mVolume++;
    }
    //调低音量
    void VolumeDown(){
        if (this->mVolume <= minVol){
            return;
        }
        this->mVolume--;
    }
    //更换电视频道
    void ChannelUp(){
        if (this->mChannel >= maxChannel){
            return;
        }
        this->mChannel++;
    }
    void ChannelDown(){
        if (this->mChannel <= minChannel){
            return;
        }
        this->mChannel--;
    }
    //展示当前电视状态信息
    void ShowTeleState(){
        cout << "开机状态:" << (mState == On ? "已开机" : "已关机") << endl;
        if (mState == On){
            cout << "当前音量:" << mVolume << endl;
            cout << "当前频道:" << mChannel << endl;
        }
        cout << "-------------" << endl;
    }
private:
    int mState; //电视状态,开机,还是关机
    int mVolume; //电视机音量
    int mChannel; //电视频道
};

//电视机调台只能一个一个的调,遥控可以指定频道
//电视遥控器
class Remote{
public:
    Remote(Television* television){
        pTelevision = television;
    }
public:
    void OnOrOff(){
        pTelevision->OnOrOff();
    }
    //调高音量
    void VolumeUp(){
        pTelevision->VolumeUp();
    }
    //调低音量
    void VolumeDown(){
        pTelevision->VolumeDown();
    }
    //更换电视频道
    void ChannelUp(){
        pTelevision->ChannelUp();
    }
    void ChannelDown(){
        pTelevision->ChannelDown();
    }
    //设置频道 遥控新增功能
    void SetChannel(int channel){
        if (channel < Television::minChannel || channel > Television::maxChannel){
            return;
        }
        pTelevision->mChannel = channel;
    }

    //显示电视当前信息
    void ShowTeleState(){
        pTelevision->ShowTeleState();
    }
private:
    Television* pTelevision;
};


//直接操作电视
void test01(){

    Television television;
    television.ShowTeleState();
    television.OnOrOff(); //开机
    television.VolumeUp(); //增加音量+1
    television.VolumeUp(); //增加音量+1
    television.VolumeUp(); //增加音量+1
    television.VolumeUp(); //增加音量+1
    television.ChannelUp(); //频道+1
    television.ChannelUp(); //频道+1
    television.ShowTeleState();
}

//通过遥控操作电视
void test02(){
    //创建电视
    Television television;
    //创建遥控
    Remote remote(&television);
    remote.OnOrOff();
    remote.ChannelUp();//频道+1
    remote.ChannelUp();//频道+1
    remote.ChannelUp();//频道+1
    remote.VolumeUp();//音量+1
    remote.VolumeUp();//音量+1
    remote.VolumeUp();//音量+1
    remote.VolumeUp();//音量+1
    remote.ShowTeleState();
}

 

#include "stdafx.h"
#include <iostream>
using namespace std;

class A;

class B
{
public:
    void showA(A& obj);
};

class A
{
    friend void Fun(A& obj);//全局友元函数
public:
    A(int a) { m_a = a; }
    void show() { cout <<"void show() "<< m_a << endl; }
    friend void B::showA(A& obj);//某类的成员做友元函数
private:
    int m_a;
    friend class B;//友元类
};

void Fun(A& obj)
{
    cout <<"void Fun(A& obj)"<< obj.m_a << endl;
}


void B::showA(A& obj)
{
    cout << "void B::showA(A& obj)" <<obj.m_a << endl;
}

void test()
{
    A a(10);
    a.show();
    Fun(a);
    B b;
    b.showA(a);
}

int main()
{
    test();
    system("pause");
    return 0;
}

 

posted @ 2019-02-25 16:12  吹过田野的风  阅读(236)  评论(0编辑  收藏  举报