友元基础概念定义friend 是 C 特有机制允许外部函数 / 外部类直接访问本类的 private、protected 私有 / 保护成员核心弊端破坏面向对象封装性打破类的访问权限隔离工程开发中少用语言对比Java、C# 没有友元机制依靠接口、get/set 函数替代友元功能设计初衷C 兼容 C 语言面向过程写法的妥协方便兼容老式 C 代码、简化运算符重载等场景友元函数使用规则在类内部用friend声明外部函数声明不受 public/private/protected 位置限制友元函数不属于当前类没有 this 指针代码示例#includeiostreamusingnamespacestd;classPerson{private:// 私有成员外部普通函数无法直接访问intmoney1000;public:// 声明全局函数visit为友元friendvoidvisit(Person p);};// 友元函数实现voidvisit(Person p){// 直接访问Person私有成员moneycout私有存款p.moneyendl;}intmain(){Person p;visit(p);return0;}友元类核心特性语法类内声明 friend class 类名;单向性友元关系不能传递、不能双向自动生效● 若 A 声明 B 为友元 → B 能访问 A 私有但 A 不能访问 B 私有需要 B 内部额外声明 A整个友元类的所有成员函数都可以访问当前类的私有 / 保护成员。代码示例单向友元#includeiostreamusingnamespacestd;// 前置声明classGirl;classBoy{public:voidlook(Girl g);};classGirl{private:intsecret99;// 声明Boy为友元类Boy全部函数可访问Girl私有friendclassBoy;};voidBoy::look(Girl g){// 合法Boy是Girl友元读取私有secretcout女孩私有数据g.secretendl;}intmain(){Boy b;Girl g;b.look(g);return0;}补充上例中 Girl 是 Boy 的普通类Boy 没有被 Girl 设为友元Girl 的函数不能访问 Boy 私有成员友元关键限制友元关系单向不会自动互成朋友友元关系不可继承父类的友元不会自动成为子类的友元友元不可传递A 友元 B、B 友元 C不代表 A 友元 C友元只是访问通道友元函数不属于本类不能用 对象.友元函数() 调用优缺点总结优点简化运算符重载、跨类数据交互代码兼容 C 旧代码减少复杂封装接口的编写缺点严重破坏封装私有成员对外暴露不符合面向对象设计规范权限管理混乱难以管控谁能修改内部私有数据Java/C# 等现代面向对象语言直接舍弃该特性开发规范建议尽量不用友元优先设计 public 对外接口get/set 函数仅运算符重载等特殊极简场景才少量使用友元函数杜绝大规模使用友元类避免类之间权限完全透明
C++友元
友元基础概念定义friend 是 C 特有机制允许外部函数 / 外部类直接访问本类的 private、protected 私有 / 保护成员核心弊端破坏面向对象封装性打破类的访问权限隔离工程开发中少用语言对比Java、C# 没有友元机制依靠接口、get/set 函数替代友元功能设计初衷C 兼容 C 语言面向过程写法的妥协方便兼容老式 C 代码、简化运算符重载等场景友元函数使用规则在类内部用friend声明外部函数声明不受 public/private/protected 位置限制友元函数不属于当前类没有 this 指针代码示例#includeiostreamusingnamespacestd;classPerson{private:// 私有成员外部普通函数无法直接访问intmoney1000;public:// 声明全局函数visit为友元friendvoidvisit(Person p);};// 友元函数实现voidvisit(Person p){// 直接访问Person私有成员moneycout私有存款p.moneyendl;}intmain(){Person p;visit(p);return0;}友元类核心特性语法类内声明 friend class 类名;单向性友元关系不能传递、不能双向自动生效● 若 A 声明 B 为友元 → B 能访问 A 私有但 A 不能访问 B 私有需要 B 内部额外声明 A整个友元类的所有成员函数都可以访问当前类的私有 / 保护成员。代码示例单向友元#includeiostreamusingnamespacestd;// 前置声明classGirl;classBoy{public:voidlook(Girl g);};classGirl{private:intsecret99;// 声明Boy为友元类Boy全部函数可访问Girl私有friendclassBoy;};voidBoy::look(Girl g){// 合法Boy是Girl友元读取私有secretcout女孩私有数据g.secretendl;}intmain(){Boy b;Girl g;b.look(g);return0;}补充上例中 Girl 是 Boy 的普通类Boy 没有被 Girl 设为友元Girl 的函数不能访问 Boy 私有成员友元关键限制友元关系单向不会自动互成朋友友元关系不可继承父类的友元不会自动成为子类的友元友元不可传递A 友元 B、B 友元 C不代表 A 友元 C友元只是访问通道友元函数不属于本类不能用 对象.友元函数() 调用优缺点总结优点简化运算符重载、跨类数据交互代码兼容 C 旧代码减少复杂封装接口的编写缺点严重破坏封装私有成员对外暴露不符合面向对象设计规范权限管理混乱难以管控谁能修改内部私有数据Java/C# 等现代面向对象语言直接舍弃该特性开发规范建议尽量不用友元优先设计 public 对外接口get/set 函数仅运算符重载等特殊极简场景才少量使用友元函数杜绝大规模使用友元类避免类之间权限完全透明