C++友元
程序员文章站
2022-05-31 10:42:37
友元 只有本类中的成员函数可以访问本类的私有成员,阻止其他访问,但在某些情况下。我们要访类的私有成员,如果把私有成员定义为共有的话,就破坏了类的隐藏性,这是我们就用到了友元。 友元(friend)机制可以允许类外的函数和其他类访问本类的私有成员。 友元在类中声明,以 关键字firend 开始,可以在 ......
友元
只有本类中的成员函数可以访问本类的私有成员,阻止其他访问,但在某些情况下。我们要访类的私有成员,如果把私有成员定义为共有的话,就破坏了类的隐藏性,这是我们就用到了友元。
友元(friend)机制可以允许类外的函数和其他类访问本类的私有成员。
友元在类中声明,以关键字firend开始,可以在类中任意位置声明。友元函数虽然定义在类内,但其并不是类成员,所以其不受public
,protected
,private
的影响.
友元函数
将非成员函数声明为友元函数
友元函数是不在类中的函数,但是可以访问类内的所有成员的函数。
#include <bits/stdc++.h> using namespace std; class a { private : int x; friend void query_pri(a a); //在private里定义的友元函数 public : friend void query_pub(a a); //在public里定义的友元函数 a(int a = 0) : x(a) {} protected : friend void query_pro(a a); //在protected里定义的友元函数 }; //注意,三个query函数不是类成员函数 void query_pri(a a) { printf("%d\n", a.x); } void query_pro(a a) { printf("%d\n", a.x); } void query_pub(a a) { printf("%d\n", a.x); } int main() { a a(10); query_pub(a); query_pro(a); query_pri(a); //三个函数都可以执行,说明友元函数不受在类中定义位置的影响 //说明友元函数不是类成员函数 return 0; }
注意:友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要通过对象访问。
例如,我们把query_pub
函数改为这样
void query_pub() { printf("%d\n", x); }
就会报错。
之前提到过,成员函数会自动隐式的增加this指针
,来访问对象的成员,但三个query
函数不是类成员函数,没有this指针
,这样编译器就不知道使用哪个对象,所以必须通过参数传递对象,并在访问时说明对象。
将其他类的成员函数声明成友元函数
友元函数不仅可以使非成员函数,也可以是另一个类的成员函数。
#include <bits/stdc++.h> using namespace std; class b; //注意这里 class a { public : void query(b oth); }; class b { private : int b; public : b(int x) : b(x) {} friend void a::query(b oth); }; void a::query(b oth) { printf("%d", oth.b); } int main() { b b(10); a a; a.query(b); return 0; }
输出:
10
这段代码里注意两点
- 程序中对b类提前进行了声明,因为在b类定义之前就用到了它,就像如果要使用一个变量时要提前声明一样。
-
query
函数的声明和实现被分开,把query
放在了b类的后面,因为在query
中用到了b中的成员,若不提前声明b,就不能确定b类中是否拥有该成员,就会报错。
一个函数可以被多个类声明为友元函数,可以访问多个类的private
和protected
成员。
友元类
类也可以被声明为友元,友元类的所有成员函数都是另一个类的友元函数,可以访问另一个类中的protected
和private
成员。
格式:
friend class class_name
如将b声明为a的友元,那b中的所有成员函数都是类a的友元函数,可以访问a中的所有成员。
如:
#include <bits/stdc++.h> using namespace std; class a { private : int x, y; public : friend class b; a(int a = 10, int b = -20) : x(a), y(b) {}; }; class b { public: void print(a a) { printf("%d\n", a.x); } void print_abs(a a) { printf("%d\n", abs(a.y)); } }; int main() { a a; b b; b.print(a), b.print_abs(a); return 0; }
使用友元类时注意:
- 友元关系不能被继承。
- 友元关系是单向的,不具有交换性。若类b是类a的友元,类a不一定是类b的友元,要看在类中是否有相应的声明。
- 友元关系不具有传递性。若类b是类a的友元,类c是b的友元,类c不一定是类a的友元,同样要看类中是否有相应的声明