c++中如何定义友元函数_c++ friend关键字用法实例【汇总】

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

友元函数不是类的成员,但它能访问类的私有和保护成员——关键在于 friend 关键字必须出现在类内部的声明中,且仅声明,不定义;定义必须在类外,像普通函数一样。

友元函数声明必须写在类内部,且不能带 public/private

很多人误以为 friend 函数可以像成员函数那样放在 public 区域里,或者加 const 修饰。其实:friend 声明本身不受访问控制符影响,它只是“授权”,不是“归属”。

  • friend 声明只能出现在类定义内部,位置任意(publicprivateprotected 区都可,但推荐统一放在顶部或底部)
  • 声明时不能加 publicstaticvirtualconst 等修饰符
  • 声明末

    尾必须有分号,这是易漏点
  • 函数定义必须在类外,且不能用 :: 作用域解析符(因为它不是成员)

友元函数参数至少有一个是当前类类型(或引用/指针)

否则编译器无法建立“访问授权”的上下文关系。常见错误是把友元函数写成无参函数,或只传基本类型,这时即使加了 friend,也无法访问私有成员。

  • 典型签名: friend void print(const MyClass& obj);friend bool operator==(const MyClass& a, const MyClass& b);
  • 若参数全是 intstd::string 等非本类类型,该函数根本不会获得访问权限
  • 传值、传引用、传指针均可,但推荐传 const& 避免拷贝和意外修改

友元破坏封装性,但重载运算符时几乎无法避免

很多人想用友元实现 ==,却忘了左操作数是标准类型(如 std::ostream),没法把 operator 写成 ostream 的成员函数——这时友元是唯一合规解法。

  • operator 必须是友元(或类内定义为成员,但那样 std::cout 就变成 obj ,语义错乱)
  • 二元运算符如 +== 若需左操作数为非本类对象(比如 5 + obj),也得靠友元支持隐式转换场景
  • 友元不继承:基类的友元对派生类私有成员无访问权
  • 友元不传递:A 是 B 的友元,B 是 C 的友元,不代表 A 能访问 C 的私有成员
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 修饰不一致,问题极难排查。