• 28,友元的尴尬能力


    1. 友元的概念

    (1)友元C++中的一种关系

    (2)友元关系发生在函数与类之间或类与类之间

    (3)友元关系是单项的不能传递

    复制代码
    class Point
    {
        double x;
        double y;
        friend void func(Point& p);  //声明func为Point类的友元函数-----将Point类和全局函数finc()联系起来,----使得func()具有的超能力,可以访问Point全部成员
    } 
    
    void func(Point& p){};     //全局函数,参数是类的引用接受一个Ponit对象p作为参数---------通过参数对象名p,可以访问Point类内的任何成员
    复制代码

    2. 友元的用法

    (1)在类中以friend关键字声明友元

    (2)类的友元可以是其它类或者具体函数

    (3)友元不是类的一部分,也不受类中访问级别的限制,可以直接访问具体类的所有成员--------超能力

    (4)用友元注意事项

      ①友元关系不具备传递性

           

      ②类的友元可以是其它类的成员函数(即其它类的成员函数作为该类的友元函数

      ③类的友元可以是某个完整的类(即所有的成员函数都是友元

     1 #include <stdio.h>
     2 #include <math.h>
     3 
     4 class Point
     5 {
     6 private:
     7 
     8     double x;
     9     double y;
    10 
    11 public:
    12 
    13     Point(double x, double y)
    14     {
    15         this->x = x;
    16         this->y = y;
    17     }
    18 
    19     double getX(){return x;}
    20     double getY(){return y;}
    21 
    22     void getXY()
    23     {
    24         printf("x = %f, y = %f
    ", x, y);
    25     }
    26 
    27    friend double Distance(Point& p1, Point& p2);  //Distance是point的友元,Distance可以访问类的一切成员,main不可以
    28 
    29 };
    30 
    31 
    32 
    33 double Distance(Point& p1, Point& p2)
    34 {
    35      double ret = 0;
    36 
    37      //ret=sqrt((p2.x-p1.x)*(p2.x-p1.x) +
    38 
    39               (p2.y-p1.y)*(p2.y-p1.y));     //error-----------Distance全局函数与point没有关系,Distance是类的外部,当然不能引用类中的私有成员!
    40     //上面改写成
    41      ret = (p2.getY()- p1.getY()) * (p2.getY() - p1.getY()) +
    42            (p2.getX() - p2.getX()) * (p2.getX() - p1.getX());    //调用8次函数,效率低,---引入友元解决
    43 
    44      //引入友元
    45      ret = (p2.y()- p1.y()) * (p2.y() - p1.y()) +
    46            (p2.x() - p2.x()) * (p2.x() - p1.x());
    47 
    48      ret=sqrt(ret);
    49 
    50      return ret;
    51 
    52 }
    53 
    54 int main()
    55 {
    56     Point p1(1, 2);
    57 
    58     Point p2(10, 20);
    59 
    60     p1.getXY();
    61 
    62     p2.getXY();
    63 
    64     printf("p1(%f,%f)
    ", p1.getX(), p1.getY());          //mian 和Point
    65     printf("p2(%f,%f)
    ", p2.getX(), p2.getY());
    66     printf("|(p1,p2)|=%f
    ", Distance(p1, p2));
    67 
    68     return 0;
    69 
    70 }

    3. 友元的尴尬

    (1)友元为了兼顾C语言的高效而诞生的,但直接破坏面向对象的封装性(每个类定义的私有成员,不能被外界访问)c++当作c语言,不符合初心

    (2)友元在实际产品中的高效是得不偿失的在现代软件工程中己经逐渐被遗弃

    【编程实验】友元的深入分析

     1 #include<stdio.h>  
     2 
     3 //类与类之间也有友元关系,但是没有传递性
     4 //破坏了对象的封装性,如:不能随便访问类的私有成员
     5 
     6 class Classc
     7 {
     8     const char* n;      //字符指针,n表示类对象的名字
     9 public:
    10     Classc(const char* n)
    11     {
    12         this->n = n;    //this指向当前调用类的对象
    13     }
    14 
    15     friend class Classb;        //友元,b可以访问c的私有成员
    16 };
    17 
    18 class Classb
    19 {
    20     const char* n;             //字符指针,n表示类对象的名字
    21 public:
    22     Classb(const char* n)
    23     {
    24         this->n = n;
    25     }
    26 
    27     //访问c的名字,就可以访问类Classc的各个数据元素
    28     void getClassName(Classc& c)
    29     {
    30         printf("c.n=%s
    ", c, n);
    31     }
    32 
    33     friend class Classa;            //友元,a可以访问b的私有成员
    34 };
    35 
    36 class Classa
    37 {
    38     const char* n;                  //字符指针,n表示类对象的名字
    39 public:
    40     Classa(const char* n)
    41     {
    42         this->n = n;
    43     }
    44 
    45     //访问b的名字,就可以访问到Classb的数据元素
    46     void getClassName(Classb& b)
    47     {
    48         printf("b.n=%s
    ", b, n);
    49     }
    50 
    51 };
    52 
    53 
    54 int main()
    55 {
    56     //A是B的友元类,B是C的友元类,但A不能自动传递为C的友元类
    57 
    58     Classa A("O");
    59     Classb B("P");
    60     Classc C("Q");
    61 
    62     A.getClassName(B);  //B
    63     B.getClassName(C);  //c
    64 
    65 
    66     return 0;
    67 }

    4. 小结

    (1)友元是为了兼顾C语言的高效而诞生的

    (2)友元直接破坏了面向对象的封装性

    (3)友元关系不具备传递性

    (4)类的友元可以是其它类的成员函数

    (5)类的友元可以是某个完整的类

  • 相关阅读:
    Spring MVC @PathVaribale注解
    Android XML解析并将数据存放在数据库中
    Android平台SoundPool 和 MediaPlayer
    Android编程获取网络连接状态(3G/Wifi)及调用网络配置界面
    程序员必备的七大面向对象设计原则(二)
    Android setRequestedOrientation用法
    Linux系统IP路由基础[第1部分]
    Android中解析XML
    Android学习笔记(6)————Android的线程与进程
    Eclipse最全快捷键
  • 原文地址:https://www.cnblogs.com/liuyueyue/p/13376981.html
Copyright © 2020-2023  润新知