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)类的友元可以是某个完整的类