首页 > 代码库 > 第28课 - 友元的尴尬能力

第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)\n", p1.getX(), p1.getY());
46     printf("p2(%f, %f)\n", p2.getX(), p2.getY());
47     printf("|(p1, p2)| = %f\n", 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\n", 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\n", c.n);//非合法,因为在类C中,并没将A声明为友元类
42     }
43 
44     void getClassBName(ClassB& b)
45     {
46         printf("b.n = %s\n", 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)类的友元可以是某个完整的类

 

第28课 - 友元的尴尬能力