zoukankan      html  css  js  c++  java
  • 2.19 C++友元函数和友元类

    参考: http://www.weixueyuan.net/view/6350.html

    总结:

      借助friend关键字将其声明为友元函数,结果,在display函数体内,我们就能访问private属性的title和price成员变量

      除了顶层函数可以被定义为友元函数之外,其它类的成员函数同样可以声明为本类的友元函数

    • 例3中我们将date类声明为time类的友元类,此时date类中的所有函数都将成为time类的友元函数。
    • date类是time类的友元类,但是time类不是date类的友元类。友元关系是单向的,而不是双向的。如果需要将time类也声明名为date类的友元类,则需要另外在date类中声明。
    • 友元关系不能传递,假设A类是B类的友元类,B类是C类的友元类,这两点并不能得出A类是C类的友元类。
    • 友元类会破坏数据的安全性,使用时宁缺毋滥。如果不是能够极大提高程序运行效率的情况,最好不要用友元。

    通过friend关键字,我们可以将不属于当前类的一个函数在当前类中加以声明,该函数便可以成为当前类的友元函数。

    例1:

    #include<iostream>
    using namespace std;
    
    class book
    {
    public:
        book(){}
        book(char* a, double p);
        friend void display(book &b);
    private:
        double price;
        char * title;
    };
    
    book::book(char* a, double p) 
    {
        title = a;
        price = p;
    }
    
    void display(book &b)
    {
        cout<<"The price of "<<b.title<<" is $"<<b.price<<endl;
    }
    
    int main()
    {
        book Alice("Alice in Wonderland",29.9);
        display(Alice);
        book Harry("Harry potter", 49.9);
        display(Harry);
        return 0;
    }

    在本例中,display是一个顶层函数,在book类中,我们借助friend关键字将其声明为友元函数,结果,在display函数体内,我们就能访问private属性的title和price成员变量。这就是友元函数的作用。友元函数可以访问这个类中的私有成员。如果这个display函数不是book类的友元函数,则在函数体中还必须调用public属性的成员函数。在此例中需要注意的是友元函数的形参是类对象的引用,同时在访问私有成员变量时必须要加上对象名。

    除了顶层函数可以被定义为友元函数之外,其它类的成员函数同样可以声明为本类的友元函数,如例2所示。

    例2:

    #include<iostream>
    using namespace std;
    
    class time;
    
    class date
    {
    public:
        date(int y,int m,int d);
        void display(time &t);
    private:
        int year;
        int month;
        int day;
    };
    
    class time
    {
    public:
        time(int s,int m,int h);
        friend void date::display(time & t);
    private:
        int second;
        int minute;
        int hour;
    };
    
    time::time(int s,int m,int h)
    {
        second = s;
        minute = m;
        hour = h;
    }
    
    date::date(int y,int m,int d)
    {
        year = y;
        month = m;
        day = d;
    }
    
    void date::display(time &t)
    {
        cout<<"The time is:"<<endl;
        cout<<year<<"/"<<month<<"/"<<day<<" ";
        cout<<t.hour<<":"<<t.minute<<":"<<t.second<<endl;
    }
    
    int main()
    {
        date d(2015,1,16);
        time t(20,2,30);
        d.display(t);
        return 0;
    }

    在本例中定义了两个类time和date,在time类中有hour、minute和second三个成员变量,分别代表时分秒,在date类中有year、month和day三个成员变量,分别代表年月日信息。为了能够共同显示年月日时分秒信息,我们在date类中声明了一个display函数,并且将该函数设置为time类的友元函数,如此一来,该函数既能访问date类中的私有成员变量,同时又能访问time类中的私有成员变量,打印时间自然不在话下。

    这个例子有几点需要注意一下。首先要注意的是date类的定义必须出现在time类之前,这么做是为了使得display函数的函数声明能够在声明为友元函数之前。其次,display函数的形参为time类对象的引用,而time类又必须定义在date类之后,如此一来只能先将time类声明在date类之前了,如class time;这一语句即是为了声明time类。第三点就是需要将display函数的定义放到time类定义的后面,这是因为display函数中必须用到time类中的私有成员变量,因此在使用之前,这些成员变量必须先声明出来。这三个需要注意顺序的地方需要大家特别关注一下,顺序一定不能搞错了,否则都是无法通过编译的。

    无论是类的成员函数还是顶层函数,它们都是可以被多个类声明为友元函数的,如此一来就可以访问多个类中的私有成员变量,但是为了保证数据的安全,友元函数的使用宁缺毋滥。

    除了可以利用friend关键字声明友元函数之外,我们还可以将其它类声明为当前类的友元类。友元类声明的语法非常简单,即为“friend 类名;”。

    例3:

    #include<iostream>
    using namespace std;
    
    class time;
    class date
    {
    public:
        date(int y,int m,int d);
        void display(time &t);
    private:
        int year;
        int month;
        int day;
    };
    
    class time
    {
    public:
        friend date;
        time(int s,int m,int h);
    private:
        int second;
        int minute;
        int hour;
    };
    
    time::time(int s,int m,int h)
    {
        second = s;
        minute = m;
        hour = h;
    }
    
    date::date(int y,int m,int d)
    {
        year = y;
        month = m;
        day = d;
    }
    
    void date::display(time &t)
    {
        cout<<"The time is:"<<endl;
        cout<<year<<"/"<<month<<"/"<<day<<" ";
        cout<<t.hour<<":"<<t.minute<<":"<<t.second<<endl;
    }
    
    int main()
    {
        date d(2015,1,16);
        time t(20,2,30);
        d.display(t);
        return 0;
    }

    在本例中,我们将date类声明为time类的友元类,则此时date类中的所有成员函数都将转化为time类的友元函数,可以访问time类中的所有成员。毫无疑问,date类中display函数同样也会成为time类的友元,因此利用time类对象t的引用便可以访问time类的私有成员变量了。此函数中类的声明及定义、函数的声明及定义位置同样需要注意。

    关于友元还有几点需要注意:

      • 例3中我们将date类声明为time类的友元类,此时date类中的所有函数都将成为time类的友元函数。
      • date类是time类的友元类,但是time类不是date类的友元类。友元关系是单向的,而不是双向的。如果需要将time类也声明名为date类的友元类,则需要另外在date类中声明。
      • 友元关系不能传递,假设A类是B类的友元类,B类是C类的友元类,这两点并不能得出A类是C类的友元类。
      • 友元类会破坏数据的安全性,使用时宁缺毋滥。如果不是能够极大提高程序运行效率的情况,最好不要用友元。
  • 相关阅读:
    Sqoop
    Mediawiki
    TextMate 通用快捷键
    Wind7外接显示器选择拓展模式后,鼠标只能往右移动才能切换到外接显示器上,不能修改切换方向
    用Nginx+Lua(OpenResty)开发高性能Web应用
    netty4.0.x源码分析—bootstrap
    mysql分组合并GROUP_CONCAT
    Only POT texture can be compressed to PVRTC format
    手机屏幕左下角显示Fastboot mode是什么情况?
    判断UNITY版本号
  • 原文地址:https://www.cnblogs.com/yongpan/p/7544242.html
Copyright © 2011-2022 走看看