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) ", p1.getX(), p1.getY()); 51 printf("p2(%f, %f) ", p2.getX(), p2.getY()); 52 printf("|(p1, p2)| = %f ", 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 ", 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 ", b.n); 44 } 45 46 /* 47 void getClassCName(ClassC& c) // 友元不具备传递性; 48 { 49 printf("c.n = %s ", 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,类的友元可以是某个完整的类;