• 友元


    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;
    }
  • 相关阅读:
    NDK 在 Android studio如何使用(Android studio NDK)
    懒人习惯之ButterKnife Zelezny
    Android 如何在Eclipse 引入外部纯Java项目(不是打成Jar使用)
    android:ellipsize="end" 失效或者 相关的Bug
    Python 父目录获取
    RecyclerView中实现headerView,footerView功能
    Win7/Win8.1右键菜单技巧:应用程序任意加
    使用android-resource-remover优化资源使用率和lint-result.xml如果导出
    Android Studio 1.1.0版本以上 优化编译
    关于Eclipse如何加入Gradle文件与Android Studio两个平台一起开发,工作目录不发生变化
  • 原文地址:https://www.cnblogs.com/mmc9527/p/10431493.html
Copyright © 2020-2023  润新知