什么是友元?

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

 

以上是关于什么是友元?的主要内容,如果未能解决你的问题,请参考以下文章

友元函数

C++友元详解

第28课 - 友元的尴尬能力

友元超英雄(二十二)

友元相关

友元函数