C++中的友元
1,友元的超能力在初始的时候能力很好、很实用,但是随着软件工程的发展,大家 越来越觉得友元的超能力是那么的不够友好,于是在实际的开发中,友元的超 能力就被遗弃了;
2,友元的概念:

1,友元是 C++ 中的一种关系;
1,这种关系发生在两个实体之间;
2,友元关系发生在函数与类之间或者类与类之间;
3,友元关系时单向的,不能传递;
3,友元的解析:
1,在类中以 frined 关键字声明友元;
2,类的友元可以是其它类或者具体函数;
3,友元不是类的一部分;
4,友元不受类中访问级别的限制;
5,友元可以直接访问具体类的所有成员;
1,这就是友元的超能力;
4,友元的语法:
1,在类中用 friend 关键字对函数或类进行声明;
2,代码示例:
1 class Point
2 {
3 double x; // 私有;
4 double y; // 私有;
5
6 friend void func(Point& p); // func() 全局函数是 Point 类的友元,func() 可以访问 Point 类的所有成员,但是 func() 不是 Point 的成员函数;
7 };
8
9 void func(Point& p)
10 {
11 }
5,友元的使用初探编程实验:
1,main.cpp 文件:
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; // 成员函数有一个 this 指针,用于指向当前对象;
12 this->y = y; // 将参数 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 bouble func(Point& p1, Point& p2)
29 {
30 double ret = 0;
31
32 /*
33 ret = (p2.getY() - p1.getY()) * (p2.getY() - p1.getY()) +
34 (p2.getX() - p1.getX()) * (p2.getX() - p1.getX()); //这个式中调用了八次函数,C++ 诞生初期,这么简单的计算要调用八次函数,和 C 相比效率低下,但是 C++ 设计初期要兼容包括 C 的高效等的一切特性,但是面向对象就有信息隐藏,所以诞生了友元;
35 */
36
37 ret = (p2.y - p1.y) * (p2.y - p1.y) +
38 (p2.x - p1.x) * (p2.x - p1.x);
39
40 ret = sqrt(ret);
41
42 return ret;
43 }
44
45 int main()
46 {
47 Point p1(1, 2);
48 Point p2(10, 20);
49
50 printf("p1(%f, %f)\n", p1.getX(), p1.getY());
51 printf("p2(%f, %f)\n", p2.getX(), p2.getY());
52 printf("|(p1, p2)| = %f\n", func(p1, p2));
53
54 return 0;
55 }
2,输出结果:
p1(1.000000, 2.000000)
p2(10.000000, 20.000000)
|(p1, p2)| = 20.124612
6,友元的缺陷:
1,友元是为了兼顾 C 语言的高效而诞生的;
2,友元直接破坏了面相对象的封装性;
1,私有成员就不应该被外界访问;
3,友元在实际产品中的高效是得不偿失的;
1,破坏了封装性,导致很多的开发者将 C++ 作为 C 语言来使用;
4,友元在现代软件工程中已经逐渐遗弃;
1,成熟的产品中很少见到友元的身影;
2,Java、C#、D 这些语言都诞生自 C++,但是都没有支持友元关系;
3,在以后开发中,如果不是特别的关系,不要使用友元;
7,注意事项:

1,友元关系不具备传递性;
2,类的友元可以是其他类的成员函数;
3,类的友元可以是某个完整的类;
1,所有的成员函数都是友元,可以访问所有成员;
8,友元的深入分析编程实验:
1,main.cpp 文件:
1 #include <stdio.h>
2
3 class ClassC
4 {
5 const char* n; // 用于表示这个类的对象的名字;
6 public:
7 ClassC(const char* n)
8 {
9 this->n = n; // 当前对象的初始值需要用构造函数的参数设置;
10 }
11
12 friend class ClassB; // B 是 C 的友元;
13 };
14
15 class ClassB
16 {
17 const char* n;
18 public:
19 ClassB(const char* n)
20 {
21 this->n = n;
22 }
23
24 void getClassCName(ClassC& c) // 直接访问 C 的名字;
25 {
26 printf("c.n = %s\n", c.n);
27 }
28
29 friend class ClassA; // A 是 B 的友元;
30 };
31
32 class ClassA
33 {
34 const char* n;
35 public:
36 ClassA(const char* n)
37 {
38 this->n = n;
39 }
40
41 void getClassBName(ClassB& b) // 直接访问 B 的名字;
42 {
43 printf("b.n = %s\n", b.n);
44 }
45
46 /*
47 void getClassCName(ClassC& c) // 友元不具备传递性;
48 {
49 printf("c.n = %s\n", c.n); // ‘const char* ClassC::n’ is private within this context;
50 }
51 */
52 };
53
54 int main()
55 {
56 ClassA A("A");
57 ClassB B("B");
58 ClassC C("C");
59
60 A.getClassBName(B);
61 B.getClassCName(C);
62
63 return 0;
64 }
2,输出结果:
b.n = B
c.n = C
9,小结:
1,友元是为了兼顾 C 语言的高效而诞生的;
2,友元直接破坏了面相对象的封装性;
3,友元关系不具备传递性;
4,类的友元可以是其它类的成员函数;
5,类的友元可以是某个完整的类;


浙公网安备 33010602011771号