C++友元类使用场景_C++类间协作设计方式讲解
技术百科
冰川箭仙
发布时间:2026-01-01
浏览: 次 友元类是为解决特定协作场景下深度交互与封装保护的矛盾而设,如容器与迭代器、类簇构造、单元测试等,需克制使用且明确声明。
友元类不是为了“打破封装”,而是为了解决特定协作场景下,类与类之间需要深度交互但又不便暴露公有接口的矛盾。它的使用应当克制、明确且有充分理由。
需要共享内部数据结构的紧密耦合组件
当两个类在逻辑上构成一个整体,比如容器类和它的迭代器类,迭代器必须能直接访问容器的底层指针或节点结构,但把所有成员设为 public 会破坏容器的数据完整性约束。此时将迭代器声明为容器的友元类,既保证了访问效率,又维持了封装边界——只有迭代器能越界访问,其他外部代码依然被隔离。
- 典型例子:std::vector 的私有成员 _M_start、_M_finish 是其 iterator 可直接读写的,但普通用户代码完全不可见
- 注意:友元关系不传递,也不继承;A 是 B 的友元,不意味着 A 的子类或 B 的子类自动获得该权限
实现类簇(Class Cluster)时统一构造与资源管理
某些设计中,对外只暴露一个抽象接口类,而实际由多个具体实现类分工协作(如不同压缩格式的解码器)。主接口类可能需要创建并初始化这些实现类,并直接设置其私有状态(如缓冲区地址、解码上下文),但又不希望把这些初始化逻辑暴露为 public 接口。这时可将主接口类声明为各实现类的友元。
- 避免把构造参数全塞进构造函数,也避免为初始化过程添加冗余的 set_xxx() 方法
- 关键点:友元仅用于构造/配置阶段的可信协作,运行时仍通过公有接口通信
单元测试类需验证私有行为逻辑
测试代码本身不属于产品模块,但需要检查类的私有成员是否按预期更新(例如缓存命中计数、状态机当前 stage)。将测试类(如 TestMyClass)声明为被测类的友元,可在测试中直接断言私有变量值,而不必为测试破环设计——无需添加仅供测试用的 public getter。
- 建议将测试类命名清晰(如 MyClassTest),并在头文件中用 #ifdef TEST 宏控制友元声明,确保发布版不包含该关系
- 这不是偷懒替代测试设计,而是对关键不变量做白盒验证的合理手段
基本上就这些。友元类不是语法糖,而是协作契约——它让两个类在编译期就约定好“我信你,只信你”。用对了,代码更清晰;滥用,则封装形同虚设。
# 也不
# 多个
# 并在
# 迭代
# 数据结构
# 设为
# public
# c++
# class
# 指针
# 子类
# 构造函数
# 接口
# 封装
# 继承
# 单元测试
# 形同虚设
# 仅供
相关栏目:
<?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局域网共享怎么设置 Win11文件夹网络
- Win11怎么更改默认打开方式_Win11关联文件
- php删除数据怎么软删除_添加is_del字段标记
- mac怎么安装pip_MAC Python pip
- Win11怎么卸载Photos应用_Win11卸载
- Windows10电脑怎么设置自动连接WiFi_W
- c++ reinterpret_cast怎么用 c
- php怎么下载安装后设置默认字符集_utf8配置步
- Win11怎么查看激活状态_查询Windows 1
- Windows10系统怎么查看显卡型号_Win10
- Win10系统更新错误0x80240034怎么办
- Win11任务栏怎么固定应用 Win11将软件图标
- php怎么下载安装并配置环境变量_命令行调用PHP
- Linux如何使用grep搜索文件内容_Linux
- 使用类变量定义字符串常量时如何实现类型安全的 Li
- php8.4xdebug无法调试怎么办_php8.
- Win11如何设置鼠标灵敏度_Win11鼠标灵敏度
- Mac电脑进水了怎么办_MacBook进水后紧急处
- Win11怎么更改账户头像_Windows 11自
- Win11如何设置ipv6 Win11开启IPv6
- Win11开机自检怎么关闭_跳过Win11开机磁盘
- Win11怎么关闭内容自适应亮度_Windows1
- Windows10怎么用“讲述人”读屏辅助 Win
- Win10如何卸载微软拼音输入法 Win10只保留
- Win11 explorer.exe频繁崩溃_修复
- php命令行怎么运行_通过CLI模式执行PHP脚本
- c++如何判断文件是否存在_c++ filesys
- Win11玩游戏全屏闪退怎么办_Win11全屏优化
- Win10任务栏天气和资讯怎么关闭 Win10禁用
- Win11视频默认播放器怎么改_Win11关联第三
- PhpStorm怎么调试PHP代码_PhpStor
- Win11怎么关闭触控板_Win11笔记本禁用触摸
- 如何在 ACF 中正确更新嵌套多层 Group 字
- Win11怎么设置单手模式_Win11触控键盘布局
- Win11如何设置电源计划_Win11电源计划优化
- 如何提升Golang JSON序列化性能_Gola
- 如何使用Golang匿名函数_快速定义临时函数逻辑
- Windows蓝屏错误0x00000023怎么修复
- php会话怎么开启_session_start函数
- Win11怎么自动隐藏任务栏_Win11全屏显示设
- VSC怎么创建PHP项目_从零开始搭建项目的步骤【
- Win11如何卸载OneDrive_Win11卸载
- Win11怎么关闭粘滞键_彻底禁用Windows
- Mac怎么设置登录项_Mac管理开机自启动程序【教
- 如何在Golang中实现微服务负载均衡_Golan
- Win11怎么清理C盘系统日志_Win11清理系统
- c++中如何使用虚函数实现多态_c++多态性实现原
- Windows10如何重置此电脑_Windows1
- Python对象生命周期管理_创建销毁解析【教程】
- Python文本编码与解码_跨平台解析说明【指导】

QQ客服