【C++】友元friend的含义和用法
friend
的含义
在 C++ 中,friend
关键字用于声明某个函数或类为当前类的友元(friend)。友元可以访问类的私有成员(private)和受保护成员(protected),即使这些成员对于普通的非友元类或函数是不可见的。
语法
- 声明一个函数为友元:
class MyClass { friend void MyFriendFunction(); // 函数是 MyClass 的友元 };
- 声明另一个类为友元:
class MyClass { friend class AnotherClass; // AnotherClass 是 MyClass 的友元 };
friend
的作用
class CMonitor
{
friend CMonitorTimer;
};
这里声明了 CMonitorTimer
是 CMonitor
类的友元。这意味着:
CMonitorTimer
类可以直接访问CMonitor
的所有成员,包括私有成员和受保护成员。- 这种访问不受
public
、protected
和private
限制。
这样写的好处
这种设计通常是为了在两个类之间实现更紧密的协作,同时保留必要的封装。以下是其优点:
1. 实现更紧密的关联
CMonitorTimer
是专门为CMonitor
服务的辅助类。- 通过友元关系,
CMonitorTimer
可以直接访问CMonitor
的私有或受保护成员,而无需通过公共接口,避免了额外的开销或复杂性。
2. 保留封装性
- 使用友元时,
CMonitor
的私有成员仍然对其他类保持不可见。 - 不必为了让
CMonitorTimer
访问这些私有成员而将其提升为public
,从而保证了封装性。
3. 简化代码
- 如果没有
friend
关系,为了实现类似的功能,可能需要提供大量的public
或protected
的 getter 和 setter 函数,增加了代码复杂性。 - 通过友元,可以直接在
CMonitorTimer
中访问CMonitor
的私有成员,简化代码逻辑。
实践
CMonitor
类和一个辅助计时器类 CMonitorTimer
:
#include <iostream>
using namespace std;
class CMonitor {
private:
int data; // 私有数据成员
public:
CMonitor(int val) : data(val) {}
void Display() const {
cout << "CMonitor Data: " << data << endl;
}
friend class CMonitorTimer; // 声明友元类
};
class CMonitorTimer {
public:
void ModifyMonitor(CMonitor& monitor) {
// 直接访问 CMonitor 的私有成员
monitor.data += 10;
}
};
int main() {
CMonitor monitor(5);
monitor.Display();
CMonitorTimer timer;
timer.ModifyMonitor(monitor); // 修改私有成员
monitor.Display();
return 0;
}
输出:
CMonitor Data: 5
CMonitor Data: 15
注意事项
1. 滥用友元破坏封装性
- 友元打破了类的封装性,因此不要轻易滥用友元。
- 友元关系应该仅用于两个高度相关、需要紧密协作的类或函数。
2. 难以维护
- 如果友元关系使用过多,类之间的耦合度可能会增加,代码的维护性会降低。
- 尽量保持友元的使用简单、明确,避免复杂的依赖链。
3. 调试和阅读代码时需要额外注意
- 友元允许类直接操作另一个类的私有成员,代码逻辑可能会隐晦,给调试和理解代码带来额外负担。