c++如何实现装饰器模式_c++ 类包装与功能动态扩展【实战】
发布时间 - 2026-01-08 00:00:00 点击率:次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 ConcreteCompone
nt)) 这种写法在 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 的脉搏来安排。
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
使用spring连接及操作mongodb3.0实例
宙斯浏览器文件分类查看教程 快速筛选视频文档与图片方法
百度浏览器如何管理插件 百度浏览器插件管理方法
Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤
如何实现建站之星域名转发设置?
无锡营销型网站制作公司,无锡网选车牌流程?
Laravel中的Facade(门面)到底是什么原理
Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程
中山网站推广排名,中山信息港登录入口?
Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知
如何用y主机助手快速搭建网站?
如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)
Laravel如何使用Blade组件和插槽?(Component代码示例)
常州企业网站制作公司,全国继续教育网怎么登录?
千库网官网入口推荐 千库网设计创意平台入口
如何快速搭建安全的FTP站点?
Laravel如何实现API资源集合?(Resource Collection教程)
如何用低价快速搭建高质量网站?
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
javascript中的数组方法有哪些_如何利用数组方法简化数据处理
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】
Claude怎样写约束型提示词_Claude约束提示词写法【教程】
Laravel集合Collection怎么用_Laravel集合常用函数详解
米侠浏览器网页图片不显示怎么办 米侠图片加载修复
javascript事件捕获机制【深入分析IE和DOM中的事件模型】
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
javascript基于原型链的继承及call和apply函数用法分析
HTML透明颜色代码在Angular里怎么设置_Angular透明颜色使用指南【详解】
Laravel如何实现API版本控制_Laravel版本化API设计方案
Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】
高端网站建设与定制开发一站式解决方案 中企动力
HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】
如何选择PHP开源工具快速搭建网站?
Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能
Laravel如何实现密码重置功能_Laravel密码找回与重置流程
太平洋网站制作公司,网络用语太平洋是什么意思?
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
Laravel如何使用Passport实现OAuth2?(完整配置步骤)
Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出
奇安信“盘古石”团队突破 iOS 26.1 提权
Python文件异常处理策略_健壮性说明【指导】
如何在万网自助建站中设置域名及备案?
Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析
如何批量查询域名的建站时间记录?
如何快速使用云服务器搭建个人网站?
高性价比服务器租赁——企业级配置与24小时运维服务
大同网页,大同瑞慈医院官网?
软银砸40亿美元收购DigitalBridge 强化AI资料中心布局
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化


nt))