zoukankan      html  css  js  c++  java
  • C++学习随笔之十二:友元

    C++中的友元包括友元函数和友元类。友元函数在前面章节类的使用中已经知道了,现在主要讨论友元类

    1.友元类:

    前面已经将友元函数用于类的扩展接口中,类并非只能友元函数的,也可以将类作为友元,即友元类。

    友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。       

          当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:

          friend class 类名;

          其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。

          例如,以下语句说明类B是类A的友元类:

          class A

          {

                 …

          public:

                 friend class B;

                 …

          };

          经过以上说明后,类B的所有成员函数都是类A的友元函数,能存取类A的私有成员和保护成员。

          使用友元类时注意:

                (1) 友元关系不能被继承。 

                (2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

                (3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明

    下面是模拟电视机和遥控器的简单示例程序:

    头文件tv.h:

    #pragma once

    #include <iostream>

    using namespace std;

    //电视类

    class Tv

    {

    private:

    int state;//on or off

    int volume;// volume

    int maxchannel;//maximum number of maxchannel

    int channel;// current channel

    int mode;//broadcast or cable

    int input;//TV or VCR

    public:

    friend class Remote;// 遥控器类

    enum{Off,On};

    enum{MinVal,MaxVal = 20};

    enum{Broadcast,Cable};

    enum{TV,VCR};

    Tv(int s = Off,int mc = 100):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 SetMode(){mode =(mode == Broadcast)?Cable:Broadcast;}

    void SetInput(){input =(input == TV)?VCR:TV;}

    void Settings()const;//display all settings

    };

    //遥控器类

    class Remote

    {

    private:

    int mode;

    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 SetMode(Tv & t){t.SetMode();}

    void SetInput(Tv & t){t.SetInput();}

    void SetChan(Tv & t,int c){t.channel = c;}

    };

    实现文件tv.cpp:

    #include <iostream>

    #include "tv.h"

    using namespace std;

    bool Tv::VolUp()

    {

    if(volume<MaxVal)

    {

    volume++;

    return true;

    }

    else

    return false;

    }

    bool Tv::VolDown()

    {

    if(volume>0)

    {

    volume--;

    return true;

    }

    else

    return false;

    }

    void Tv::ChanUp()

    {

    if(channel<maxchannel)

    {

    channel ++;

    }

    else

    channel = 1;

    }

    void Tv::ChanDown()

    {

    if(channel>0)

    {

    channel--;

    }

    else

    channel = maxchannel;

    }

    void Tv::Settings()const

    {

    cout <<"Tv is" << (state == Off? "Off":"On") <<endl;

    if(state == On)

    {

    cout <<"Volume setting = "<<volume<<endl;

    cout <<"Channel setting = "<<channel<<endl;

    cout <<"Mode = "<<mode<<endl;

    cout <<"Input = " <<input <<endl;

    }

    }

    测试文件mian.cpp:

    #include <iostream>

    #include "tv.h"

    using namespace std;

    int _tmain(int argc, _TCHAR* argv[])

    {

    Tv tcl;

    cout <<"Initial settings for tcl:"<<endl;

    tcl.Settings();

    tcl.OnOff();

    tcl.ChanUp();

    cout <<"Adjusted settings for tcl:"<<endl;

    tcl.Settings();

    Remote rmt;

    rmt.SetChan(tcl,24);

    rmt.VolUp(tcl);

    cout <<"settings after by Remote:"<<endl;

    tcl.Settings();

    return 0;

    }

    友元成员函数:如果不需要一个类的所有方法的公有接口,可以选择仅让特定的类成员成为另一个类的友元,而不必让整个类成为友元。这样做药注意的是声明和定义的顺序。

    如上面程序中让Remote::SetChan()成为Tv类的友元的方法是,在Tv类声明中将其声明为友元:

    class Tv

    {

    public:

    friend void Remote ::SetChan(Tv & t,int c);

    };

    不过若要使编译器知能够处理这个语句,必须让它知道Remote的定义,因此应将Remote类的定义放在Tv的定义前面,但是,SetChan方法中有Tv的参数,所以应将Tv的定义放在Remote定义之前,为了避开这种循环,采用前向声明:

    class Tv;

    class Remote{...};

    class Tv{....};

    能否想下面这样顺序呢?

    class Remote;

    class Tv{...};

    class Remote{..};

    答案是不能。(要知道为什么哦?)

    2.嵌套类:

    嵌套类,顾名思义,是一个类嵌套在另一个类中。在C++中,可以将类声明放在另一类中。在另一个类中声明的类被称为嵌套类(nested class)。它通过提供新的类型类作用域避免名称混乱。包含类的成员函数可以创建和使用被嵌套类的对象;而仅当声明位于公有部分,才能将包含类的外面使用嵌套类,而且必须使用作用域解析操作符。

  • 相关阅读:
    django-ForeignKey,OneToOneField,ManyToManyField
    django-HttpResponse,render,redirect
    django-常见问题勘误
    django-个人网站之环境配置(一)
    django-表单之数据保存(七)
    django-表单之模型表单渲染(六)
    django-表单之手动渲染(五)
    Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法与解析
    流媒体传输协议详解之---RTSP认证
    在YUV图像上根据背景色实现OSD反色
  • 原文地址:https://www.cnblogs.com/JczmDeveloper/p/2964828.html
Copyright © 2011-2022 走看看