• 简单易懂的C++类的友元教程(friend)。全局函数做类友元,一个类做另一个类的友元,一个类中某个成员函数做友元。过程中顺序很重要哦。最后附有完整实现代码


    目录:

    一:友元的作用

    二:全局函数做友元

    注意事项:

    三:整个类做友元

    (1)先对两个类进行声明

    (2)将要被声明为友元类的类定义在另一个类上方

    (3)两个类构造函数的实现顺序

      (4)最后一步(实在不知道取什么名了.....)

     四:类中成员函数作友元

    一:友元的作用

    为了可以在类外部某些特定的作用域内访问类内的私有属性。

    对于class来说,它里面默认有三个区域。

    下面我们通过一张图来更加直观的了解一下。

    可以看到,我们在类外通过对象直接访问类内的私有属性Bedroom,会报错而访问公共权限下的 Liviing_room却不会出错。这就是因为test1不是这个building类的友元。

    如果我们将这个test1定义为building的友元函数那么在这个test1函数内部,就可以直接访问building类的私有权限中的属性。(有路径就行)。话不多说,我们直接上正题。

    二:全局函数做友元

    其实相对来说,我们在创建一个类的时候,通常都会将它的成员属性进行私有化的,那如果我非要使用,test1函数直接访问到building类的私有属性,那该咋办呢?

    其实非常简单,我们只需要加上两句代码就可以使得在test1函数内部访问building类的私有属性了。

    可以看到,在添加了这两条代码之后,编译器刚才报出的警告没有了。现在只要有路径,就可以直接访问building函数内部,并且可以修改私有属性的数据。 

    注意事项:

    因为这里的代码都是从上到下顺序执行的,那么我们尽量要在类上面加上友元函数test1的声明,虽然不加编译器也能跑得过。但是该加还是得加。

    三:整个类做友元

    这里就要注意了:因为在程序运行起来时,一直都是顺序执行的,所以在这里要严格按照顺序去实现。(我刚开始没有按照顺序去实现,所以编译器会老是报错,没有这个类,没有那个类的。)

    (1)先对两个类进行声明

    (2)将要被声明为友元类的类定义在另一个类上方

    这里为了方便观察,所以我将两个类分开截图了,但是通过行号依然可以看出,先定义的breather类,后定义的building类。

    这里要注意:在实现这两个类的定义时,对于类中的成员函数与构造函数,我们都只进行简单声明 ,不要在这里实现他们,因为代码顺序执行的原因,会报错!!!

    (3)两个类构造函数的实现顺序

    我们一定要按照顺序去先实现,building类的构造函数,后实现breather类的构造函数,因为在一个类(主类)中包含其他类(从类)时,创建一个主类对象,编译器是会优先生成从类的。 

    (4)最后一步(实在不知道取什么名了.....)

    在building类中声明一下breather类是它的友元类,并将breather类中的vist函数实现,可以看到它现在确实可以直接访问,building类的私有属性了

     我们直接让代码走起来,可以看到结果很明确。通过breather中的vist函数,可以直接访问building类的私有属性了。

     四:类中成员函数作友元

    在了解了上面两种友元的定义方式,这个实现起来就比较简单了,直接将类的友元的声明代码修改一下进行了。

    现在在breather类中,只有在vist函数体内才能访问building类的私有属性了。 

    最后附上完整代码

    1. #include<iostream>
    2. #include<string>
    3. using namespace std;
    4. class building;
    5. class breather;
    6. void test1();
    7. class breather
    8. {
    9. public:
    10. breather();
    11. void vist();
    12. void vist1();
    13. building* buil;
    14. };
    15. class building
    16. {
    17. friend void test1();
    18. //friend class breather;
    19. friend void breather::vist();
    20. public:
    21. building();
    22. string living_room;//客厅
    23. private:
    24. string Bedroom;//卧室
    25. };
    26. building::building()//先实现building的构造函数
    27. {
    28. this->Bedroom = "私人卧室";
    29. this->living_room = "公共客厅";
    30. }
    31. breather::breather()//实现breather类的构造函数
    32. {
    33. this->buil = new building;
    34. }
    35. void breather::vist()
    36. {
    37. cout << this->buil->living_room << endl;
    38. cout << this->buil->Bedroom<< endl;
    39. }
    40. void breather::vist1()
    41. {
    42. cout << this->buil->living_room << endl;
    43. //cout << this->buil->Bedroom << endl;
    44. //为了对比vist函数
    45. }
    46. void test2()
    47. {
    48. breather b1;
    49. b1.vist();
    50. }
    51. void test1()
    52. {
    53. building b1;
    54. cout << b1.Bedroom << endl;
    55. cout << b1.living_room << endl;
    56. b1.living_room = "客厅";
    57. b1.Bedroom = "卧室";
    58. }
    59. int main()
    60. {
    61. test2();
    62. return 0;
    63. }

  • 相关阅读:
    【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(9 月 4 日论文合集)
    【从头构筑C#知识体系】0.3 值类型和引用类型
    kotlin实现ArrayDeque
    基于JavaSwing开发图书销售管理系统 课程设计 大作业 毕业设计
    7-25 念数字
    在 Spring Security中授予权限与角色
    CompletableFuture异步编排(两任务组合——两个任务必须都完成才触发另一个任务 )
    CodeTON Round 6 (Div 1 + Div 2, Rated, Prizes!)(A - E)
    计算机网络复习(一~三)
    JavaCV音视频开发宝典:rtsp转推到rtp(非TS流方式),及使用TS流发送解决sdp缺失问题
  • 原文地址:https://blog.csdn.net/qq_51004011/article/details/125413810