友元函数不是类的成员但可访问私有/保护成员,声明必须在类内用friend关键字(不加访问修饰符和const等,需分号),定义在类外;参数至少一个为本类类型(推荐const&),用于运算符重载等场景。
友

friend 关键字必须出现在类内部的声明中,且仅声明,不定义;定义必须在类外,像普通函数一样。
public/private
很多人误以为 friend 函数可以像成员函数那样放在 public 区域里,或者加 const 修饰。其实:friend 声明本身不受访问控制符影响,它只是“授权”,不是“归属”。
friend 声明只能出现在类定义内部,位置任意(public、private 或 protected 区都可,但推荐统一放在顶部或底部)public、static、virtual、const 等修饰符:: 作用域解析符(因为它不是成员)否则编译器无法建立“访问授权”的上下文关系。常见错误是把友元函数写成无参函数,或只传基本类型,这时即使加了 friend,也无法访问私有成员。
friend void print(const MyClass& obj); 或 friend bool operator==(const MyClass& a, const MyClass& b);
int、std::string 等非本类类型,该函数根本不会获得访问权限const& 避免拷贝和意外修改很多人想用友元实现 或 ==,却忘了左操作数是标准类型(如 std::ostream),没法把 operator 写成 ostream 的成员函数——这时友元是唯一合规解法。
operator 必须是友元(或类内定义为成员,但那样 std::cout 就变成 obj ,语义错乱)+、==、 若需左操作数为非本类对象(比如 5 + obj),也得靠友元支持隐式转换场景
class Box {
private:
double width;
double height;
public:
Box(double w = 1.0, double h = 1.0) : width(w), height(h) {}
// 友元声明:注意分号,不加 public,不加 const
friend void printWidth(const Box& box);
friend Box operator+(const Box& a, const Box& b);
};
// 类外定义:不加 friend,不加 Box::,就是普通函数
void printWidth(const Box& box) {
std::cout << "Width: " << box.width << std::endl; // OK:访问私有成员
}
Box operator+(const Box& a, const Box& b) {
return Box(a.width + b.width, a.height + b.height); // OK
}
最容易被忽略的是:友元函数的声明和定义必须类型完全一致(包括 const、引用、模板特化),否则链接时报 “undefined reference”。尤其在头文件中声明、源文件中定义时,拼写或 const 修饰不一致,问题极难排查。
来电咨询