友元类能访问声明方类所有非静态private和protected成员(含字段、非静态成员函数、嵌套类型),但不包括静态私有成员、private构造函数,且友元关系不可继承、不双向、需前置声明。

友元类能访问哪些成员
友元类获得的是对声明方类所有非静态 private 和 protected 成员的完全访问权,包括字段、非静态成员函数、嵌套类型(如 struct Inner),但不包括静态私有成员——除非显式通过作用域解析或对象实例访问。它不能访问被声明为 private 的构造函数(除非是友元类自己的构造逻辑中调用),也不能绕过 explicit 限制。
友元关系不是双向的,必须显式声明
如果 class A 声明 friend class B;,那只有 B 的所有成员函数能访问 A 的私有成员;A 依然不能访问 B 的任何私有内容。想实现双向协作,必须在双方类定义中各自写一句 friend 声明。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 前置声明通常不可少:
class B;必须出现在A定义之前,否则编译器不认识B - 友元声明位置无关访问控制区:
friend class B;放在public、private或类定义开头都一样有效 - 友元关系不可继承:即使
B派生出C,C也不能自动获得对A的访问权限
避免把整个类设为友元,优先考虑友元成员函数
全类友元相当于给对方开了“万能钥匙”,风险高。更精细的做法是只授权特定成员函数:
class Girl {
std::string diary_;
friend void Boy::readDiary(const Girl&); // 只放行这个函数
};
- 这样
Boy::confess()能读diary_,但Boy::peek()就不能 - 需要前向声明
class Boy;,且Boy的完整定义必须在Girl定义之后(否则无法解析Boy::readDiary) - 比全类友元更易审计、更难误用,也更符合“最小权限”原则
模板友元类的权限控制更需谨慎
用 template<typename t> friend class Helper;</typename> 会授予 Helper<int></int>、Helper<:string></:string> 等所有实例访问权;若只想授权某一个特化,得写成 friend class Helper<int>;</int>。
- 模板友元声明必须在类模板定义内部完成,外部补声明无效
- 如果
Helper<t></t>自身也有私有成员,它仍不能反向访问你的类——友元权限不传递 - 模板友元容易引发 ODR(One Definition Rule)问题,尤其在头文件中多次包含时,建议配合
inline或static辅助函数封装访问逻辑
friend class X;,X 所有未来新增的成员函数都会自动获得访问权,而你可能根本没意识到。所以与其事后加注释说“请勿滥用”,不如一开始就把访问逻辑收敛到一两个明确命名的辅助函数里。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










