前言
友元是一种定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。
正文
1 2 3 4 5
| #pragma once class Box{ int hp; int mp; };
|
老样子写个类。
友元函数
当类中成员没有声明是public的时候,即便你用类当参数模板,也是无法调用的。
1 2 3
| void test(Box &b){ b.hp = 100; }
|
结果就是无法访问。
而按照友元的逻辑,需要告诉这个类你有一个朋友,friend void test(Box &b);
这样你的朋友才能了解你的相关事物。
然后就不会报错了。
说明友元访问私有变量是没啥问题,还能访问私有函数
1 2 3 4
| int getHp(){ return this->hp; }
|
1 2 3 4 5
| void test(Box &b){ b.hp = 100; std::cout << b.getHp(); }
|
结果都没问题,也就是说友元函数可以访问类的私有成员。
还有就是类和函数啥的因为都是顺序执行,所以当一个类中调用另一个类的时候,这个类如果在后面才定义,编译器也是会报错的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #pragma once class Box{ int hp; int mp;
int getHp(){ return this->hp; }
friend void test(Box &b); friend void getHP(Box &b1, Hz &h1); };
class Hz{ int hp; };
|
就拿这种情况,我们getHP参数调用Box本身和Hz,但是Hz在后面定义.
这个时候就要学习函数,将声明放置于顶部,定义放在后面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #pragma once class Hz; class Box{ int hp; int mp;
int getHp(){ return this->hp; }
friend void test(Box &b); friend void getHP(Box &b1, Hz &h1); };
class Hz{ int hp; };
|
这样就解决这个小毛病。
友元类
写法差不多,friend class 类名
。
作用就是可以创建这个类的对象,可以访问类中的私有成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #pragma once
class Hz; class Box{ int hp; int mp;
int getHp(){ return this->hp; }
friend void test(Box &b); friend void getHP(Box &b1, Hz &h1); friend class Hz; };
class Hz{ int hp; int mp;
void getMp(){ Box b1; std::cout << b1.getHp() << std::endl; } };
|
这里还涉及到人际关系,就是你拿它当朋友,但是它不一定拿你当朋友。
具体表现在类中,就是虽然你声明了一个友元类,它可以访问你了,但是你不能访问它。
1 2 3 4
| void getMp(){ Hz h1; h1. }
|
还挺勾心斗角的。。。
这个解决方法在于双方都要声明,双认证一样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #pragma once #include<iostream>
class Hz; class Box{ int hp; int mp;
int getHp(){ return this->hp; }
void getMp(){ Hz h1; h1.mp; }
friend void test(Box &b); friend void getHP(Box &b1, Hz &h1); friend class Hz; };
class Hz{ int hp; int mp;
void getMp(){ Box b1; std::cout << b1.getHp() << std::endl; }
friend class Box; };
|
但是显然这种逻辑关系很麻烦。
结语
但是要注意朋友的朋友不一定就是朋友
即A,有朋友B和C,但是B和C之间不一定就是朋友,因为友元不具备关系传递。
而且友元本质上会破坏类的封装性,所以只有万不得已的情况下才会选择友元,友元这种不是一种平等的关系。