优缺点:友元破坏了面向对象的封装性,但在某些频繁访问成员变量的地方可以提高性能。
1.友元函数
通过 friend
将一个函数声明为某个类的友元函数,那么该函数就能访问这个类的所有成员(包括public/protected/private)。
友元函数不属于类成员,其不受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;
}
2.友元类
如下代码所示,通过 friend
将类 B
声明为类 A
的友元类,那么类 B
的所有成员函数都能直接访问类 A
的所有成员(包括public/protected/private)。
注意:每个类都负责控制自己的友元类和友元函数。
- 友元关系不能被继承;
- 友元关系是单向的,比如类B是类A的友元类,但这并不代表类A是类B的友元类;
- 友元关系没有传递性,比如类B是类A的友元类,类C是类B的友元类,但这并不代表类C是类A的友元类。
#include <iostream>
using namespace std;
class B; // 类B的声明
class A
{
private:
int data;
void display()
{
cout << "data = " << data << endl;
}
friend class B; // 将类B声明为类A的友元类
};
class B
{
public:
void change(int x, A& a)
{
a.data = x;
a.display();
}
};
int main()
{
A a;
B b;
b.change(50, a);
return 0;
}
3.友元成员函数
A.h
#ifndef __A_H
#define __A_H
#include <iostream>
#include "B.h"
class A
{
private:
int data;
void display();
friend void B::change(int x, A& a); // 将类B的成员函数change()声明为类A的友元函数
};
#endif
A.cpp
#include "A.h"
void A::display()
{
std::cout << "data = " << data << std::endl;
}
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;
}