文章预览:
- 一. 前言
- 二. 友元函数
- 三. 友元类
- 四. 友元成员函数
一. 前言
众所周知,C++
控制对类对象私有成员的访问。通常,公有类方法(public
)提供唯一的访问途径,但是有时候这种限制太严格,以至于不适合特定的编程问题。
在这种情况下,C++
提供了另外一种形式的访问权限:友元,友元有3
种:
- 友元函数;
- 友元类;
- 友元成员函数;
优缺点
- 优点:通过让函数成为类的友元(即:友元函数),可以赋予该函数与类的成员函数相同的访问权限,使其可以访问本类
protected、private
成员,在某些频繁访问成员变量的地方可以提高性能。 - 缺点:友元破坏了面向对象的封装性。
二. 友元函数
1、通过friend
将一个函数(友元函数是个函数)声明为某个类的友元函数,那么该函数就能访问这个类的所有成员(成员变量、成员函数),无论是public,private,protected
。
2、因为友元函数不属于类成员,所以其不受public/protected/private
的限制,放在public/protected/private
下声明都行。
代码展示:
#include <iostream>
using namespace std;
class A
{
private:
int data;
void display(){
cout << "data = " << data << endl;
}
friend void change(int x, A& a); // 将函数change()声明为类A的友元函数
};
void change(int x, A& a)
{
a.data = x;
a.display();
}
int main()
{
A a;
change(10, a);
return 0;
}
三. 友元类
1、可以在类A
中把类B
声明为类A
的友元类,此时,在类B
(类A
的友元类)的成员函数中,可以访问类A
的所有成员(成员变量、成员函数),无论是public,private,protected
。
2、由于友元类不属于类成员,所以友元类的声明不受public、protected、private
的影响。
代码展示(Tip
:为什么需要类B
的声明):
#include <iostream>
using namespace std;
class B; // 类B的声明,类A用到了类B,而类B的定义有可能在类A的定义之后导致编译出错,所以最好先声明一下类B
class A
{
private:
int data;
void display()
{
cout << "data = " << data << endl;
}
friend class B; // 将类B声明为类A的友元类(用到了类B的名字,所以需要前面声明一下class B; )
};
class B
{
public:
void change(int x, A& a)
{
a.data = x; //在类B(类A的友元类)的成员函数中,可以访问类A的所有成员(成员变量、成员函数),无论是public,private,protected
a.display();
}
};
int main()
{
A a;
B b;
b.change(50, a);
return 0;
}
注意:每个类都负责控制自己的友元类和友元函数:
- 友元关系不能被继承;
- 友元关系是单向的,比如类
B
是类A
的友元类,但这并不代表类A
是类B
的友元类; - 友元关系没有传递性,比如类
B
是类A
的友元类,类C
是类B
的友元类,但这并不代表类C
是类A
的友元类;
四. 友元成员函数
友元成员函数:即是本类的成员函数,又是其他类的友元函数。
代码展示:
A.h(Tip
:为什么使用#include "B.h"
而不用class B;
声明类B
)
#ifndef __A_H
#define __A_H
#include <iostream>
//class B; //注:声明友元成员函数不能仅仅使用类B的声明了,因为在friend void B::change(int x, A& a)不仅仅用到了类B的名字,
//还用到了其成员函数change(),系统需要先判断类B中是否有其成员函数change(),所以需要用#include "B.h"
#include "B.h"
class A
{
private:
int data;
void display()
{
std::cout << "data = " << data << std::endl;
}
friend void B::change(int x, A& a); // 该函数是友元成员函数的声明:将类B的成员函数change()声明为类A的友元函数
};
#endif
B.h
#ifndef __B_H
#define __B_H
class A; // 类A的声明
class B
{
public:
void change(int x, A& a); // 只有public的成员函数才能成为其它类的友元函数
};
#endif
B.cpp
#include "A.h"
#include "B.h"
void B::change(int x, A& a)
{
a.data = x;
a.display();
}
main.cpp
#include "A.h"
#include "B.h"
int main()
{
A a;
B b;
b.change(50, a);
return 0;
}
下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。 |