信息发布→ 登录 注册 退出

c++如何实现装饰器模式_c++ 类包装与功能动态扩展【实战】

发布时间:2026-01-08

点击量:
C++装饰器模式需手动实现,核心是接口抽象+组合+RAII:定义含virtual析构与虚函数的Component基类,装饰器通过std::unique_ptr持有并转发被包装对象,利用移动语义链式构建,确保所有权清晰与资源安全。

装饰器模式在 C++ 中没有语言级支持,必须手动实现

C++ 没有 Python 那样的 @decorator 语法,所谓“装饰器模式”是设计模式层面的结构复用方案,核心是通过组合而非继承来动态添加行为。它不依赖语法糖,而是靠接口抽象 + 指针/引用 + RAII 控制生命周期来达成。

用抽象基类定义组件接口,所有装饰器和具体组件都继承它

这是最关键的一步:没有统一接口,就无法透明替换和嵌套。接口中至少要有一个虚函数(如 operation()),且析构函数必须是 virtual,否则通过基类指针 delete 派生对象会未定义行为。

class Component {
public:
    virtual ~Component() = default;
    virtual void operation() const = 0;
};

class ConcreteComponent : public Component { public: void operation() const override { std::cout << "ConcreteComponent executed\n"; } };

常见错误:忘记 virtual ~Component() → 内存泄漏或崩溃;把 operation() 声明为非虚 → 装饰器调用时静态绑定到基类空实现。

装饰器类持有 Component 指针,并在构造时接收被包装对象

装饰器不是派生自具体类,而是组合一个 Component*(或 std::unique_ptr)。它转发调用,再在前后插入额外逻辑 —— 这就是“动态扩展”的实质。

  • 推荐用 std::unique_ptr 管理所有权,避免裸指针悬空
  • 装饰器构造函数应接受右值引用(std::unique_ptr&&)以支持链式构建
  • 不要在装饰器里拷贝被包装对象 —— 否则失去“动态”特性,变成静态包装
class LoggingDecorator : public Component {
    std::unique_ptr wrapped_;
public:
    explicit LoggingDecorator(std::unique_ptr&& w)
        : wrapped_(std::move(w)) {}
void operation() const override {
    std::cout << "[LOG] before\n";
    wrapped_->operation();
    std::cout << "[LOG] after\n";
}

};

多层装饰需注意构造顺序和内存管理边界

new TimingDecorator(new LoggingDecorator(new ConcreteComponent)) 这种写法在 C++ 里极易出错。正确做法是用移动语义逐层包裹:

auto comp = std::make_unique();
comp = std::make_unique(std::move(comp));
comp = std::make_unique(std::move(comp));
comp->operation(); // 输出日志 + 计时 + 原操作

容易踩的坑:
- 用裸指针层层 new,忘了 delete → 泄漏
- 传入左值给装饰器构造函数 → 编译失败(因只接受右值)
- 在装饰器内部直接 new 具体类并裸存指针 → 所有权混乱,RAII 失效
- 忘记装饰器也需实现全部纯虚函数(哪怕只是转发),否则无法编译

C++ 的装饰器模式真正难的不是写几行代码,而是厘清谁拥有对象、谁负责释放、在哪一层做资源初始化 —— 这些在 Python 里由解释器托管的事,在 C++ 里全得你亲手掐着 RAII 的脉搏来安排。

标签:# python  # app  # ai  # c++  
在线客服
服务热线

服务热线

4008888355

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!