因为java是单继承,jdk动态代理生成的代理类必须继承proxy类,故无法再继承目标类,只能通过实现接口来代理。

为什么不能直接继承接口类来实现 Proxy?
因为代理的核心职责是“转发调用 + 拦截控制”,不是扩展行为。如果让 Proxy 继承目标接口(比如 IService),它就必须实现所有虚函数——哪怕只是透传,这会污染代理类的职责边界,也容易在接口扩增时被动修改 Proxy。正确做法是让 Proxy 持有真实对象指针,并在每个虚函数里显式转发,把“是否转发”“如何前置/后置处理”的控制权留在自己手里。
常见错误现象:Proxy 类被 IDE 自动补全一堆空实现,编译过了但一调用就 std::bad_function_call 或空指针崩溃——原因往往是忘了初始化 m_real,或用了默认构造却没检查指针有效性。
- 始终在构造函数中要求传入非空
std::shared_ptr<t></t>或带assert(m_real)的裸指针校验 - 避免在虚函数中做耗时操作(如日志写磁盘、网络请求),否则会阻塞原调用路径
- 若需异步拦截(如统计耗时),用
std::chrono::steady_clock记录前后时间差,别用std::clock()
如何让 Proxy 支持 const 成员函数和重载函数?
虚函数表对 const 修饰符敏感:一个 void foo() const 和 void foo() 是两个完全不同的虚函数签名。Proxy 必须严格按原接口声明方式重写,否则调用会绑定到基类实现(如果有的话)或链接失败。
使用场景:接口中有 get_data() const 和 set_data(int),Proxy 要分别控制读权限和写权限。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 用
override显式标注每个虚函数,编译器会报错提醒签名不匹配 - 重载函数(如
process(int)/process(const std::string&))必须全部显式转发,不能只写一个 - 若目标接口使用了
noexcept,Proxy 对应函数也得加,否则可能破坏异常规范一致性
class ServiceProxy : public IService {
public:
explicit ServiceProxy(std::shared_ptr<iservice> real) : m_real(std::move(real)) {}
int get_value() const override {
// 前置检查:只读操作允许
return m_real->get_value();
}
void set_value(int v) override {
// 前置拦截:记录变更
log("set_value: " + std::to_string(v));
m_real->set_value(v);
}
private:
std::shared_ptr<iservice> m_real;
};</iservice></iservice>
std::shared_ptr 还是裸指针?生命周期怎么兜住?
裸指针最轻量,但极易悬垂;std::shared_ptr 自动管理生命周期,代价是原子计数开销和内存布局稍大。对轻量级 Proxy 来说,只要保证 Proxy 不比它包装的对象活得更久,裸指针完全可行——关键在于约束使用方式,而不是堆上分配。
性能影响:在高频调用路径(如每毫秒调用数百次的传感器读取接口),shared_ptr 的引用计数会带来可观开销;而裸指针 + 断言校验几乎零成本。
- 对外暴露的构造函数只接受
std::shared_ptr,内部转存为裸指针 +assert(ptr) - 禁止拷贝
Proxy对象(删掉拷贝构造/赋值),避免裸指针被多处持有导致析构混乱 - 如果真实对象可能被外部提前释放,改用
std::weak_ptr并在每次调用前lock(),但要接受调用失败的可能性
代理对象无法响应动态行为变更怎么办?
纯虚函数接口是静态绑定的,Proxy 在编译期就确定了转发逻辑。如果需要运行时切换策略(比如从“缓存代理”切到“限流代理”),靠继承体系做不到,必须引入策略对象或函数对象。
容易被忽略的地方:很多人以为加个 set_strategy() 就行,但没考虑线程安全。多个线程同时调用代理方法时,策略指针可能正被修改,导致某次调用用到半新半旧的状态。
- 用
std::atomic<:function>*></:function>存策略函数指针,确保更新是原子的 - 或者把策略封装成无状态对象(如
struct CachePolicy { static bool should_cache(...); }),避免运行时修改实例字段 - 别在虚函数里做策略判断分支(如
if (m_mode == CACHE) {...}),分支预测失败会显著拖慢热点路径
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










