代理类应通过指针(优先unique_ptr)或shared_ptr延迟绑定真实对象,避免直接实例化;需定义抽象基类接口,方法声明为virtual且析构函数为virtual;转发前后插入日志、权限等逻辑须边界清晰;警惕shared_ptr循环引用,回调用weak_ptr。

代理类必须持有真实对象的指针或引用
直接在代理类里定义真实对象的实例(如 RealSubject real)会导致构造时就创建真实对象,违背“按需创建”或“控制访问”的初衷。更常见的是用指针或智能指针延迟绑定,尤其当真实对象构造开销大、依赖外部资源,或需要空代理(如权限未满足时不初始化)时。
实操建议:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 优先使用
std::unique_ptr<realsubject></realsubject>,避免裸指针管理风险 - 若需共享所有权(如多个代理共用同一真实对象),改用
std::shared_ptr<realsubject></realsubject> - 构造函数接受
std::shared_ptr<realsubject></realsubject>或工厂函数,而非直接传入实例 - 注意:如果真实对象无默认构造函数,代理类的默认构造函数也得显式删除或禁用
代理方法调用前/后插入逻辑要明确边界
代理的核心价值不在转发,而在转发前后可控地加行为——比如日志、权限检查、缓存判断。但容易误把所有逻辑塞进代理,导致职责模糊。例如在 request() 里既做鉴权又做重试又做埋点,后期难以维护或复用。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 权限校验这类前置逻辑,放在调用
real_->request()之前,失败直接 return - 日志、耗时统计等后置逻辑,放在调用之后(注意异常安全:用 RAII 或 try/catch 包裹)
- 缓存场景下,先查缓存;命中则跳过真实对象调用;未命中再调用并写入缓存
- 不要在代理里修改真实对象的内部状态(除非设计上明确允许),否则破坏封装性
虚函数与接口抽象是代理可替换的前提
没有共同基类或接口,代理无法替代真实对象被使用者接收。C++ 中必须定义抽象基类(含纯虚函数),让 Proxy 和 RealSubject 都继承它。否则使用者代码只能写死 RealSubject 类型,代理毫无意义。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 接口类名建议用
Subject这类中性名,避免暴露实现细节(如不叫RealSubjectInterface) - 所有需被代理的方法必须声明为
virtual,且最好加上= 0纯虚,强制子类实现 - 析构函数必须是
virtual,否则通过基类指针 delete 会内存泄漏 - 若真实对象已有不可改源码的类,可用“桥接 + pimpl”或适配器包装后再代理,但复杂度上升
std::shared_ptr 传递时要注意循环引用风险
当代理持有一个 std::shared_ptr<realsubject></realsubject>,而真实对象内部又反过来保存了对代理的 std::shared_ptr<proxy></proxy>(比如回调注册),就会形成循环引用,导致两者永远无法析构。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 代理到真实对象的引用是单向的,禁止真实对象反向强引用代理
- 如需回调,真实对象应接受
std::weak_ptr<proxy></proxy>或裸指针(确保生命周期可控) - 调试时可打印
use_count()辅助判断,比如构造后立即输出proxy_->real_->use_count() - 简单场景下,干脆不用
shared_ptr,改用unique_ptr+ 移动语义,彻底规避循环问题
shared_ptr 的线程安全边界和真实对象的并发访问约束,很容易被忽略。

















