• 友元函数与友元类


    采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。

         为什么要有友元函数?简单地说,通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都生命成为public(共用的),然而这做带来的问题遍是任何外部函数都可以毫无约束的访问它操作它,c++利用friend修饰符,可以让一些你设定的函数能够对这些保护数据进行操作,避免把类成员全部设置成public,最大限度的保护数据成员的安全。

         除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

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

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

     

    友元类
          友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。       
          当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:
          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的友元,同样要看类中是否有相应的申明

     

    代码举例:以下代码VC6.0下编译通过。

    一、使用友元函数调用类成员

     

    1. #include <iostream.h>  
    2. #include <string.h>  
    3.   
    4. class girl{  
    5. private:  
    6.     char *name;  
    7.     int age;  
    8.   
    9. public:  
    10.     girl(char *n,int d)  
    11.     {   
    12.         name=new char[strlen(n)+1];  
    13.         strcpy(name,n);  
    14.         age=d;  
    15.     }  
    16.   
    17.     friend void disp(girl &);   //声明为友元函数   
    18.   
    19.     ~girl(){delete name;}  
    20. };   
    21.   
    22. void disp(girl &x)              //定义友元函数  
    23. {   
    24.     cout<<"girl/'s name is:"<<x.name<<",age:"<<x.age<<endl;  
    25. }   
    26.   
    27. void main()  
    28. {   
    29.     girl e("jsfn_dai",24);  
    30.     disp(e);                    //调用友元函数  
    31. }  

     

    二、一个友元函数访问两个不同的类

     

    1. #include <iostream.h>  
    2. #include <string.h>  
    3.   
    4. class boy;   
    5. class girl{  
    6.     char name[25];  
    7.     int age;  
    8. public:  
    9.     void init(char N[],int A);  
    10.     //声明函数为girl类的友元函数  
    11.     friend void prdata(const girl plg,const boy plb);   
    12. };           
    13.   
    14. void girl::init(char N[],int A)  
    15. {   
    16.     strcpy(name,N);  
    17.     age=A;  
    18. }  
    19.   
    20. class boy{  
    21.     char name[25];  
    22.     int age;  
    23. public:  
    24.     void init(char N[],int A);  
    25.     //声明函数为boy类的友元函数  
    26.     friend void prdata(const girl plg,const boy plb);   
    27. };  
    28.   
    29. void boy::init(char N[],int A)  
    30. {   
    31.     strcpy(name,N);  
    32.     age=A;  
    33. }  
    34.   
    35. void prdata(const girl plg,const boy plb)  
    36. {   
    37.  cout<<"女孩"<<plg.name<<','<<plg.age<<"岁;"<<endl;  
    38.  cout<<"男孩"<<plb.name<<','<<plb.age<<"岁。"<<endl;  
    39. }  
    40.   
    41. void main()  
    42. {   
    43.     girl G1,G2,G3;  
    44.     boy B1,B2,B3;  
    45.     G1.init("Stacy",12);  
    46.     G2.init("Judith",13);  
    47.     G3.init("Leah",12);  
    48.     B1.init("Jim",11);  
    49.     B2.init("Micheal",13);  
    50.     B3.init("Larry",12);  
    51.     //调用友元函数  
    52.     prdata(G1,B2);  
    53.     prdata(G2,B3);  
    54.     prdata(G3,B1);  
    55. }  
     

     

    三、使用友元成员函数访问另一个类

     

    1. #include <iostream.h>  
    2. #include <string.h>  
    3.   
    4. class girl;  
    5. class boy{  
    6.     char *name;  
    7.     int age;  
    8. public:  
    9.     boy(char *N,int A)  
    10.     {   
    11.         name=new char[strlen(N)+1];  
    12.         strcpy(name,N);  
    13.         age=A;  
    14.     }  
    15.     void disp(girl &);      //声明disp()为类boy的成员函数  
    16.     ~boy(){delete name;}  
    17. };   
    18.   
    19. class girl{  
    20.     char *name;  
    21.     int age;  
    22. public:  
    23.     girl(char *N,int A)  
    24.     {   
    25.         name=new char[strlen(N)+1];  
    26.         strcpy(name,N);  
    27.         age=A;  
    28.     }  
    29.     friend void boy::disp(girl &); //声明类boy的成员函数disp()为类girl的友元函数  
    30.     ~girl(){delete name;}  
    31. };  
    32.   
    33. void boy::disp(girl &x)  
    34. {   
    35.     cout<<"boy/'s name is:"<<name<<",age:"<<age<<endl;  //访问本类对象成员  
    36.     cout<<"girl/'s name is:"<<x.name<<",age:"<<x.age<<endl;  //访问友元类对象成员  
    37. }  
    38. void main()  
    39. {   
    40.     boy b("jsfn_dai",25);  
    41.     girl g("PY",18);  
    42.     b.disp(g);  
    43. }  

     

    四、友元类

    1. #include <iostream.h>  
    2. #include <string.h>  
    3.   
    4. class girl;  
    5.   
    6. class boy{  
    7.     char *name;  
    8.     int age;  
    9. public:  
    10.     boy(char *n,int d)  
    11.     {   
    12.         name=new char[strlen(n)+1];  
    13.     strcpy(name,n);  
    14.     age=d;  
    15.     }  
    16.     void disp(girl &);  //声明disp()为类boy的成员函数  
    17.     ~boy(){delete name;}  
    18. };  
    19.   
    20. class girl{  
    21.     char *name;  
    22.     int age;  
    23.     friend boy;   //声明类boy是类girl的友元  
    24. public:  
    25.     girl(char *n,int d)  
    26.     {   
    27.         name=new char[strlen(n)+1];  
    28.         strcpy(name,n);  
    29.         age=d;  
    30.     }  
    31.     ~girl(){delete name;}  
    32. };  
    33.   
    34. void boy::disp(girl &x)  //定义函数disp()为类boy的成员函数,也是类girl的友元函数  
    35. {   
    36.     cout<<"boy/'s name is:"<<name<<",age:"<<age<<endl;  
    37.     cout<<"girl/'s name is:"<<x.name<<",age:"<<x.age<<endl;  
    38. }  
    39.   
    40. void main()  
    41. {   
    42.     boy b("jsfn_dai",25);  
    43.     girl g("PY",18);  
    44.     b.disp(g);  


  • 相关阅读:
    经典的博客有价值的博客
    关于前后端接口的异常的处理
    java重新学习记载的一些资料。
    java重新开始学习
    MFC Socket
    修复 SQLite 数据库文件
    VC++源文件编码
    VC++ 中使用 std::string 转换字符串编码
    Windows代码页、区域
    UTF-7编码
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318571.html
Copyright © 2020-2023  润新知