什么是友元?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是友元?相关的知识,希望对你有一定的参考价值。
友元函数就是以friend开头的一种破坏类的封装性的一种用法友元类的私有和保护成员在类外不可以使用
设计了一个后门,通过友元函数可以访问该对象的受限成员
1。该函数放在类内类外声明均可
2。需要通过类的对象访问
如 friend void test(Base & b)
通过b来访问成员
多用于重载操作符,尽量不要用它提供操作受限数据的函数,那样受限就没有意义了 参考技术A 朋友的钱 参考技术B 我们已知道类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。
为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。
第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)类的友元可以是某个完整的类
以上是关于什么是友元?的主要内容,如果未能解决你的问题,请参考以下文章