• 第28课


    第28课 - 友元的尴尬能力

    1. 什么是友元?

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

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

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

    2. 友元的用法

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

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

      (3)友元不是类的一部分

      (4)友元不受类中访问级别的限制

      (5)友元可以直接访问具体类的所有成员

    3. 友元的语法

      在类中用 friend 关键字对函数进行声明。

     1 #include <stdio.h>
     2 #include <math.h>
     3 
     4 class Point
     5 {
     6     double x;
     7     double y;
     8 public:
     9     Point(double x, double y)
    10     {
    11         this->x = x;
    12         this->y = y;
    13     }
    14 
    15     double getX()
    16     {
    17         return x;
    18     }  
    19 
    20     double getY()
    21     {
    22         return y;
    23     }
    24 
    25     friend double func(Point& p1, Point& p2);  // 友元函数
    26 };
    27 
    28 double func(Point& p1, Point& p2)
    29 {
    30     double ret = 0;
    31 
    32     ret = (p2.y - p1.y) * (p2.y - p1.y) + (p2.x - p1.x) * (p2.x - p1.x);
    33 
    34     ret = sqrt(ret);
    35 
    36     return ret;
    37 }
    38 
    39 int main()
    40 {
    41     Point p1(1, 2);
    42 
    43     Point p2(10, 20);
    44 
    45     printf("p1(%f, %f)
    ", p1.getX(), p1.getY());
    46     printf("p2(%f, %f)
    ", p2.getX(), p2.getY());
    47     printf("|(p1, p2)| = %f
    ", func(p1, p2));
    48 
    49     return 0;
    50 }
    友元的使用初探

    4. 友元的尴尬

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

      前面的例子中,计算两点之间的距离,如果使用C语言开发,直接访问结构体成员即可,效率很高。使用C++开发,如果按照一般的方式,需要多次调用 public 中的成员函数来访问 private 中的成员变量,该例中就调用了8次 getX() / getY(),这样就导致程序效率很低。早期的C++开发就是使用这种方式,然后被很多程序员所诟病,为了兼顾C语言的高效,由此诞生了友元。

      (2)友元直接破坏了面向对象的封装性,很多程序开发者将C++当作C语言使用了,将封装性这样的高级面向对象特性丢失了。

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

    5. 注意事项

      (1)友元关系不具备传递性。      A 是B 的友元,B 是C 的友元,但A 不 C 的友元。

      

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

      (3)类的友元可以是某个完整的类:所有的成员函数都是友元

     1 #include <stdio.h>
     2 
     3 class ClassC
     4 {
     5 private:
     6     const char* n;
     7 
     8 public:
     9     ClassC(const char* n){this->n = n;}
    10     
    11     friend class ClassB; //B是C的友元类,即B可以任意访问C
    12 };
    13 
    14 class ClassB
    15 {
    16 private:
    17     const char* n;
    18 
    19 public:
    20     ClassB(const char* n){this->n = n;}
    21 
    22     void getClassCName(ClassC& c)
    23     {
    24         printf("c.n = %s
    ", c.n);//合法,因为在类C中,己将B声明为友元类
    25     }
    26     
    27     friend class ClassA; //A是B的友元类,即A可以任意访问B
    28 };
    29 
    30 
    31 class ClassA
    32 {
    33 private:
    34     const char* n;
    35 
    36 public:
    37     ClassA(const char* n){this->n = n;}
    38 
    39     void getClassCName(ClassC& c)
    40     {
    41         //printf("c.n = %s
    ", c.n);//非合法,因为在类C中,并没将A声明为友元类
    42     }
    43 
    44     void getClassBName(ClassB& b)
    45     {
    46         printf("b.n = %s
    ", b.n);//合法,因为在类B中,己将A声明为友元类
    47     }
    48 };
    49 
    50 int main()
    51 {
    52     //A是B的友元类,B是C的友元类,但A不能自动传递为C的友元类
    53     ClassA A("A");
    54     ClassB B("B");
    55     ClassC C("C");
    56 
    57     A.getClassBName(B);//A是B的友元类,
    58     B.getClassCName(C);//B是C的友元类
    59 
    60     return 0;
    61 }
    友元的深入分析

    6. 小结

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

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

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

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

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

  • 相关阅读:
    CF D. Ehab and the Expected XOR Problem 贪心+位运算
    luogu 1903 [国家集训队]数颜色 / 维护队列 带修改莫队
    Test 1 T2 B 线段树合并
    CF812C Sagheer and Nubian Market 二分+贪心
    CF804B Minimum number of steps
    CF796D Police Stations BFS+染色
    CF796C Bank Hacking 细节
    k8s节点NotReady问题处理
    Elastic-Job快速入门
    Elastic-Job介绍
  • 原文地址:https://www.cnblogs.com/shiwenjie/p/7273101.html
Copyright © 2020-2023  润新知