ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++的友元函数和友元类(一)

2021-02-13 12:33:56  阅读:267  来源: 互联网

标签:友元 name int age C++ height Person Animal 友元类


1. 友元函数的总结

a. 友元函数不是本类的成员函数,是一个外部函数

b. 友元函数的标志是在类的内部添加的外部函数声明加上friend关键字

c. 友元函数对在类内声明的位置不要求, 在public, private和protected中都可以

d. 一个类的外部函数成为友元后,访问权限被扩展了(外部函数原先只能访问类中的public部分,友元化后可以访问public, protected, private),等同于类内部的成员函数

e. 友元函数是单向的,反过来不行,友元函数是访问类内的变量的,类内部不能反过来访问友元函数内的变量

f. 友元函数就好像在类的封装和访问权限保护上打了个“洞”,所以是对面向对象的一种破坏,所以不能滥用(影响访问权限存在的意义)

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Person
 7 {
 8 private:
 9     int age;
10 protected:
11     int height;
12 public:    
13     string name;
14     
15     Person(){}; // 空构造函数(函数构造,函数体都写在里面了)
16     Person(int age, int height, string name); //构造函数
17     friend void disp_info(Person& pn);//这里不声明友元函数,后面访问private和protected报错
18 };
19 
20 Person::Person(int age, int height, string name)
21 {
22     this->age = age;
23     this->height = height;
24     this->name = name;
25 }
26 
27 void disp_info(Person& pn)
28 {
29     cout << "name = " << pn.name << endl;
30     cout << "age = " << pn.age << endl;
31     cout << "name = " << pn.height << endl;
32 }
33 
34 int main(void)
35 {
36     Person p1(33, 173, "Nancy");
37     disp_info(p1);
38     
39     return 0;
40 }
41 
42 /*
43 输出结果:
44 name = Nancy
45 age = 33
46 name = 173
47 */
友元函数示例

 

2. 友元函数的2种实现

2.1. 友元函数的2种实现

(1)友元函数是外部函数

(2)友元函数是另一个类中的成员函数(也叫友元成员,友元成员方法,友元成员函数)

 

2.2. 类的前置声明

a. 两个类互相引用时会出现未定义的错误,这时可以用类的前置声明来解决

b. 前置声明中不包括类的详细信息,所以编译器无法得到前置声明类的size,成员等详细信息

c. 不能试图通过前置声明解决类成员的调用

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Animal;
 7 
 8 class Person
 9 {
10 private:
11     int age;
12 protected:
13     int height;
14 public:    
15     string name;
16     
17     Person(){}; // 空构造函数(函数构造,函数体都写在里面了)
18     Person(int age, int height, string name); //构造函数
19     friend void Animal :: animal(Person& pn);
20 };
21 
22 class Animal
23 {
24 public:
25     void animal(Person& pn);
26 };
27 
28 void Animal :: animal(Person& pn)
29 {
30     cout << "Person name = " << pn.name << endl;
31     cout << "Person age = " << pn.age << endl;
32     cout << "Person height = " << pn.height << endl;
33 }
34 
35 Person::Person(int age, int height, string name)
36 {
37     this->age = age;
38     this->height = height;
39     this->name = name;
40 }
41 
42 int main(void)
43 {
44     Person p1(33, 173, "Nancy");
45     Animal a1;
46     a1.animal(p1);
47     
48     return 0;
49 }
50 
51 /*
52 输出结果:
53 报错
54 invalid use of incomplete type ‘class Animal’
55 */
类的前置声明错误用法

 

d. 不能试图通过前置声明来定义类的对象,只能改为定义类对象的指针

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 //class Animal;
 7 class Person;
 8 
 9 class Animal
10 {
11 public:
12     void animal(Person& pn);
13 };
14 
15 class Person
16 {
17 private:
18     int age;
19 protected:
20     int height;
21 public:    
22     string name;
23     
24     Person(){}; // 空构造函数(函数构造,函数体都写在里面了)
25     Person(int age, int height, string name); //构造函数
26     friend void Animal :: animal(Person& pn);
27 };
28 
29 
30 
31 void Animal :: animal(Person& pn)
32 {
33     cout << "Person name = " << pn.name << endl;
34     cout << "Person age = " << pn.age << endl;
35     cout << "Person height = " << pn.height << endl;
36 }
37 
38 Person::Person(int age, int height, string name)
39 {
40     this->age = age;
41     this->height = height;
42     this->name = name;
43 }
44 
45 int main(void)
46 {
47     Person p1(33, 173, "Nancy");
48     Animal a1;
49     a1.animal(p1);
50     
51     return 0;
52 }
53 
54 /*
55 输出结果:
56 Person name = Nancy
57 Person age = 33
58 Person height = 173
59 */
类的前置声明正确用法

 

在这个例子中获得前置声明后可以先定义类对象的指针,编译器可以先不检查这个类的细节从而可以通过编译

 

2.3. 总结

设计多个类的体系时,尽量设计好层次关系为单向的(树形结构),尽量避免互相引用的情况

 

3. 友元类

3.1. 友元类的概念

(1)将A声明为B的friend class后,则A中所有成员函数都成为了类B的友元函数

 

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Person;
 7 
 8 class Animal
 9 {
10 public:
11     void animal(Person& pn);
12     void animal2(Person& pn);
13 };
14 
15 class Person
16 {
17 private:
18     int age;
19 protected:
20     int height;
21 public:    
22     string name;
23     
24     Person(){}; // 空构造函数(函数构造,函数体都写在里面了)
25     Person(int age, int height, string name); //构造函数
26     //friend void Animal :: animal(Person& pn);
27     friend class Animal;
28 };
29 
30 void Animal :: animal(Person& pn)
31 {
32     cout << "Person name = " << pn.name << endl;
33     cout << "Person age = " << pn.age << endl;
34     cout << "Person height = " << pn.height << endl;
35 }
36 
37 void Animal :: animal2(Person& pn)
38 {
39     cout << "Person name = " << pn.name << endl;
40     cout << "Person age = " << pn.age << endl;
41     cout << "Person height = " << pn.height << endl;
42 }
43 
44 Person::Person(int age, int height, string name)
45 {
46     this->age = age;
47     this->height = height;
48     this->name = name;
49 }
50 
51 int main(void)
52 {
53     Person p1(33, 173, "Nancy");
54     Animal a1;
55     a1.animal(p1);
56     a1.animal2(p1);
57     
58     return 0;
59 }
60 
61 /*
62 输出结果:
63 Person name = Nancy
64 Person age = 33
65 Person height = 173
66 Person name = Nancy
67 Person age = 33
68 Person height = 173
69 */
友元类示例

 

(2)友元类的定义和使用友元类是单向的

 

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Person;
 7 
 8 class Animal
 9 {
10 private:
11     int size;
12 public:
13     Animal(){};
14     Animal(int size);
15     void animal(Person& pn);
16     void animal2(Person& pn);
17 };
18 
19 class Person
20 {
21 private:
22     int age;
23 protected:
24     int height;
25 public:    
26     string name;
27     
28     Person(){}; // 空构造函数(函数构造,函数体都写在里面了)
29     Person(int age, int height, string name); //构造函数
30     void disp(Animal& ani);
31     //friend void Animal :: animal(Person& pn);
32     friend class Animal;
33 };
34 
35 Animal :: Animal(int size)
36 {
37     this->size = size;
38 }
39 
40 Person :: Person(int age, int height, string name)
41 {
42     this->age = age;
43     this->height = height;
44     this->name = name;
45 }
46 
47 void Person :: disp(Animal& ani)
48 {
49     cout << "size = " << ani.size << endl;
50 }
51 
52 int main(void)
53 {
54     Animal a1(30);
55     Person p1;
56     p1.disp(a1);
57 
58     return 0;
59 }
60 
61 /*
62 输出结果:
63 报错
64 */
单个定义使用友元类是单向的

 

3.2. 互为友元类

(1)两个类可以互为友元类

 

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Person;
 7 
 8 class Animal
 9 {
10 private:
11     int size;
12 public:
13     Animal(){};
14     Animal(int size);
15     void animal(Person& pn);
16     void animal2(Person& pn);
17     friend class Person;
18 };
19 
20 class Person
21 {
22 private:
23     int age;
24 protected:
25     int height;
26 public:    
27     string name;
28     
29     Person(){}; // 空构造函数(函数构造,函数体都写在里面了)
30     Person(int age, int height, string name); //构造函数
31     void disp(Animal& ani);
32     //friend void Animal :: animal(Person& pn);
33     //friend class Animal;
34 };
35 
36 Animal :: Animal(int size)
37 {
38     this->size = size;
39 }
40 
41 Person :: Person(int age, int height, string name)
42 {
43     this->age = age;
44     this->height = height;
45     this->name = name;
46 }
47 
48 void Person :: disp(Animal& ani)
49 {
50     cout << "size = " << ani.size << endl;
51 }
52 
53 int main(void)
54 {
55     Animal a1(30);
56     Person p1;
57     p1.disp(a1);
58 
59     return 0;
60 }
61 
62 /*
63 输出结果:
64 size = 30
65 */
友元类

 

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Person;
 7 
 8 class Animal
 9 {
10 private:
11     int size;
12 public:
13     Animal(){};
14     Animal(int size);
15     void animal(Person& pn);
16     void animal2(Person& pn);
17     friend class Person;
18 };
19 
20 class Person
21 {
22 private:
23     int age;
24 protected:
25     int height;
26 public:    
27     string name;
28     
29     Person(){}; // 空构造函数(函数构造,函数体都写在里面了)
30     Person(int age, int height, string name); //构造函数
31     void disp(Animal& ani);
32     //friend void Animal :: animal(Person& pn);
33     friend class Animal;
34 };
35 
36 Animal :: Animal(int size)
37 {
38     this->size = size;
39 }
40 
41 void Animal :: animal(Person& pn)
42 {
43     cout << "Person name = " << pn.name << endl;
44     cout << "Person age = " << pn.age << endl;
45     cout << "Person height = " << pn.height << endl;
46 }
47 
48 Person :: Person(int age, int height, string name)
49 {
50     this->age = age;
51     this->height = height;
52     this->name = name;
53 }
54 
55 void Person :: disp(Animal& ani)
56 {
57     cout << "size = " << ani.size << endl;
58 }
59 
60 int main(void)
61 {
62     Animal a1(30);
63     Person p1(35, 180, "Jake");
64     p1.disp(a1);
65     a1.animal(p1);
66     
67     return 0;
68 }
69 
70 /*
71 输出结果:
72 size = 30
73 Person name = Jake
74 Person age = 35
75 Person height = 180
76 */
互为友元类

 

(2)互为友元类要注意互相引用的细节

 

3.3 友元类的总结

(1)友元类就是批量制造友元函数

(2)友元类中所有全部成员都成为了友元函数,相当于打了很多洞,极大地破坏了面向对象

(3)除非确实有必要,否则建议按需定义友元函数,尽量维护面向对象

标签:友元,name,int,age,C++,height,Person,Animal,友元类
来源: https://www.cnblogs.com/Ramentherapy/p/14398371.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有