c++中如何定义友元函数_c++ friend关键字用法实例【汇总】
技术百科
冰火之心
发布时间:2026-01-15
浏览: 次 友元函数不是类的成员但可访问私有/保护成员,声明必须在类内用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),也得靠友元支持隐式转换场景 - 友元不继承:基类的友元对派生类私有成员无访问权
- 友元不传递: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 修饰不一致,问题极难排查。
# 的是
# 放在
# 这是
# 很多人
# 出现在
# 特化
# public
# 对象
# c++
# 隐式转换
# String
# int
# void
# 指针
# stream
# Static
# private
# operator
# 封装
# 成员函数
# 继承
# 作用域
# 运算符
# const
# bool
# protected
# 封装性
# print
# undefined
# 本类
# 不加
# 运算符重载
# 修饰符
# 重载运算符
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么关闭自动调节亮度_Windows11
- Win11麦克风没声音怎么设置_Win11麦克风权
- Win11怎么关闭定位服务 Win11禁止应用获取
- Win10怎样清理C盘爱奇艺缓存_Win10清理爱
- Win11怎么清理C盘下载文件夹_Win11清理下
- VSC怎么在PHP中调试MySQL_数据库交互排查
- 如何使用Golang安装API文档生成工具_快速生
- Win11怎么设置ipv4地址_Windows 1
- LINUX怎么查看进程_LINUX ps命令查看运
- Win11怎么禁用键盘自带键盘_Win11笔记本禁
- php下载安装选zip还是msi格式_两种安装包对
- 小程序里php怎么变mp4_小程序调用php生成m
- Win11用户账户控制怎么关_Win11关闭UAC
- windows系统找不到无线网络怎么办_windo
- 如何使用 Python 合并文件夹内多个 Exce
- 如何用正则与预处理结合精准拦截拼接式垃圾域名
- Win11怎么更改输入法顺序_Win11调整语言首
- Win11怎么自动隐藏任务栏_Win11全屏显示设
- c# F# 的 MailboxProcessor
- Avalonia如何实现跨窗口通信 Avaloni
- Windows11怎么自定义任务栏_Windows
- Win11怎么设置声音输出设备_Windows11
- Ajax提交表单PHP怎么接收_处理Ajax发送的
- Win11怎么关闭触摸键盘图标_Windows11
- Windows 11怎么更改锁屏超时时间_Wind
- Win11怎么设置DNS服务器_Windows11
- Win11截图快捷键是什么_Win11自带截图工具
- Windows11如何设置专注助手_Windows
- 如何高效删除 NumPy 二维数组中所有元素相同的
- mac怎么右键_MAC鼠标右键设置与触控板手势技巧
- Win11怎样安装企业微信_Win11安装企业微信
- 如何在 Go 中正确测试带 Cookie 的 HT
- Windows10怎么查看硬件信息_Windows
- Python与GPU加速技术_CUDA与Numba
- PowerShell怎么创建复杂的XML结构
- Windows10如何删除恢复分区_Win10 D
- Win11怎么关闭小组件_Win11禁用任务栏天气
- Windows10怎么备份注册表_Windows1
- Mac如何创建和管理多个桌面空间_Mac高效多任务
- Windows7如何安装系统镜像_Windows7
- 如何在Golang中实现基础配置管理功能_Gola
- Python装饰器设计思路_功能增强机制说明【指导
- Win11开机Logo怎么换_Win11自定义启动
- Win11怎么开启游戏模式_Win11优化游戏帧数
- Python网络超时处理_健壮性设计说明【指导】
- Win11怎么关闭任务栏小图标_Windows11
- Win10怎么更改用户名 Win10修改账户名称操
- Win11怎么关闭自动更新 Win11永久关闭系统
- 如何使用Golang配置安全开发环境_防止敏感信息
- Windows如何拦截腾讯视频广告_Windows

QQ客服