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

    1、为什么要引入友元函数:在实现类之间数据共享时,减少系统开销,提高效率

    c++利用friend修饰符,可以让一些你设定的函数能够对这些保护数据进行操作,避免把类成员全部设置成public,最大限度的保护数据成员的安全。

          具体来说:为了使其他类的成员函数直接访问该类的私有变量

          即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数(友元函数不是类的成员函数,是普通函数

          优点:能够提高效率,表达简单、清晰

          缺点:友元函数破环了封装机制,尽量使用成员函数,除非不得已的情况下才使用友元函数。

    2、什么时候使用友元函数:

          1)运算符重载的某些场合需要使用友元。

          2)两个类要共享数据的时候

    3、怎么使用友元函数:

    友元函数的参数:

           因为友元函数没有this指针,则参数要有三种情况

           1、  要访问非static成员时,需要对象做参数;--常用(友元函数常含有参数)

           2、  要访问static成员或全局变量时,则不需要对象做参数

           3、  如果做参数的对象是全局对象,则不需要对象做参数

    友元函数的位置:

           因为友元函数是类外的函数,所以它的声明可以放在类的私有段或公有段且没有区别。

    友元函数的调用:

           可以直接调用友元函数,不需要通过对象或指针


    友元函数  
          友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend,其格式如下:
          friend  类型 函数名(形式参数);

          友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数。
          一个函数可以是多个类的友元函数,只需要在各个类中分别声明。
          友元函数的调用与一般函数的调用方式和原理一致。

    友元类  
          友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。       
          当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:
          friend class 类名;
          其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。

     

    根据这个函数的来源不同,可以分为三种方法:

    1、普通函数友元函数:

           a) 目的:使普通函数能够访问类的友元

           b) 语法:声明位置:公有私有均可,常写为公有

                            声明: friend + 普通函数声明

                            实现位置:可以在类外或类中

                            实现代码:与普通函数相同(不加不用friend和类::)

                            调用:类似普通函数,直接调用

           c) 代码:        

    class INTEGER
    {  
    private:
        int num;
    public:
        friend void Print(const INTEGER& obj);//声明友元函数
    };
    void Print(const INTEGER& obj)     //不使用friend和类::
    {
        //函数体
    }
    void main()
    {
        INTEGER obj;
        Print(obj);//直接调用
    }

    2、类Y的所有成员函数都为类X友元函数友元类

          a)目的:使用单个声明使Y类的所有函数成为类X的友元

                            它提供一种类之间合作的一种方式,使类Y的对象可以具有类X和类Y的功能

                            具体来说:

                                    前提:A是B的友元(=》A中成员函数可以访问B中有所有成员,包括私有成员和公有成员--老忘)

                                        则:在A中,借助类B,可以直接使用~B . 私有变量~的形式访问私有变量

          b)语法:声明位置:公有私有均可,常写为私有(把类看成一个变量)

                            声明: friend + 类名---不是对象啊

                            调用:

          c)代码:

    #include <iostream>
    using namespace std;
    class girl
    {  
    private:
        char *name;  
        int age;  
        friend class  boy;   //声明类boy是类girl的友元
    public:
        girl(char *n,int age):name(n),age(age){};
    };  
    
    class boy
    {  
    private:
        char *name;  
        int age;  
    public:  
        boy(char *n,int age):name(n),age(age){};
        void disp(girl &);   
    };  
    
    void boy::disp(girl &x)       //  该函数必须在girl类定义的后面定义,否则girl类中的私有变量还是未知的    
    { 
        cout<<"boy's name is:"<<name<<",age:"<<age<<endl;
        cout<<"girl's name is:"<<x.name<<",age:"<<x.age<<endl; 
        //借助友元,在boy的成员函数disp中,借助girl的对象,直接访问girl的私有变量
        //正常情况下,只允许在girl的成员函数中访问girl的私有变量
    }
      
    void main()  
    {   
        boy b("aaa",8);  
        girl g("bbb",99);  
        b.disp(g); 
    }

    3、类Y的一个成员函数为类X的友元函数

          a)目的:使类Y的一个成员函数成为类X的友元

                 具体而言:而在类Y的这个成员函数中,借助参数X,可以直接以X。私有变量的形式访问私有变量

          b)语法:声明位置:声明在公有中 (本身为函数)

                            声明:friend + 成员函数的声明

                            调用:先定义Y的对象y---使用y调用自己的成员函数---自己的成员函数中使用了友元机制

          c)代码: 

    class girl; 
    class boy
    {  
    private:
        char *name;  
        int age;  
    public:  
        boy();
        void disp(girl &);     
    };   
     
    class girl
    {
    private:
        char *name;  
        int age;  
    public:  
        girl(char *N,int A);  
        friend void boy::disp(girl &); //声明类boy的成员函数disp()为类girl的友元函数  
    };  
     
    void boy::disp(girl &x)  
    {   
        cout<<"boy's name is:"<<name<<",age:"<<age<<endl;  //访问自己(boy)的对象成员,直接访问自己的私有变量  
        cout<<"girl's name is:"<<x.name<<",age:"<<x.age<<endl;  
        //借助友元,在boy的成员函数disp中,借助girl的对象,直接访问girl的私有变量
        //正常情况下,只允许在girl的成员函数中访问girl的私有变量  
    }  
    void main()  
    {   
        boy b();  
        girl g();  
        b.disp(g);  }

    4、在模板类中使用友元operator<<(对<<运算符的重载)

        a)使用方法:

    在模板类中声明:

    friend ostream& operator<< <>(ostream& cout,const MGraph<VexType,ArcType>& G);  

    在模板类中定义:

    template<class VexType,class ArcType>
    ostream& operator<<(ostream& cout,const MGraph<VexType,ArcType>& G)
    {
        //函数定义
    }

        b)注意:

    把函数声明非模板函数:

    friend ostream& operator<< (ostream& cout,const MGraph& G);  

    把函数声明为模板函数:

    friend ostream& operator<< <>(ostream& cout,const MGraph<VexType,ArcType>& G);  

    或:

    friend ostream& operator<< <VexType,ArcType>(ostream& cout,const MGraph<VexType,ArcType>& G);  

    说明:
     在函数声明中加入operator<< <>:是将operator<<函数定义为函数模板,将函数模板申明为类模板的友员时,是一对一绑定的
     实际的声明函数:这里模板参数可以省略,但是尖括号不可以省略

    friend ostream& operator<< <VexType,ArcType>(ostream& cout,const MGraph<VexType,ArcType>& G);  

    5、友元函数和类的成员函数的区别:成员函数有this指针,而友元函数没有this指针。

    使用友元类时注意:
        (1) 友元关系不能被继承。 
        (2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
        (3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明 

  • 相关阅读:
    hdu 1199 Color the Ball 离散线段树
    poj 2623 Sequence Median 堆的灵活运用
    hdu 2251 Dungeon Master bfs
    HDU 1166 敌兵布阵 线段树
    UVALive 4426 Blast the Enemy! 计算几何求重心
    UVALive 4425 Another Brick in the Wall 暴力
    UVALive 4423 String LD 暴力
    UVALive 4872 Underground Cables 最小生成树
    UVALive 4870 Roller Coaster 01背包
    UVALive 4869 Profits DP
  • 原文地址:https://www.cnblogs.com/balingybj/p/4778247.html
Copyright © 2011-2022 走看看