新闻中心
c++如何实现一个简单的依赖注入容器_c++控制反转(IoC)原理
控制反转是将对象创建权交给外部容器,依赖注入通过构造函数传入依赖,C++可用模板与map实现简易DI容器,支持接口绑定与自动解析,解耦代码,提升可维护性。

在C++中实现一个简单的依赖注入(Dependency Injection, DI)容器,核心目标是解耦对象的创建和使用,将控制权交给外部容器,这正是控制反转(Inversion of Control, IoC)的核心思想。我们不需要复杂的框架,通过模板和工厂模式就能实现基本功能。
1. 什么是控制反转(IoC)与依赖注入(DI)
控制反转是指程序的控制流程不再由代码内部决定,而是交由外部容器管理。比如:以前是类自己new依赖对象,现在是由容器传入。
依赖注入是IoC的一种实现方式,即把类所依赖的对象通过构造函数、函数参数等方式“注入”进来,而不是在类内部直接创建。
举个例子:假设有一个Service类依赖Logger,传统写法是在Service里直接创建Logger实例,导致两者紧耦合。而用DI后,Service只声明需要一个Logger,具体哪个Logger由容器在运行时决定并注入。
立即学习“C++免费学习笔记(深入)”;
2. 设计一个极简的DI容器
我们可以用C++模板和std::function实现一个能注册类型并自动构建对象的容器。
关键思路:
- 使用一个map保存类型ID到创建函数的映射
- 通过模板注册接口与实现的绑定
- 按需创建实例,支持单例或每次新建
代码示例如下:
#include <map>
#include <functional>
#include <typeindex>
#include <memory>
class Container {
public:
template<typename Interface, typename Implementation>
void Register() {
creators[std::type_index(typeid(Interface))] = []() {
return std::make_shared<Implementation>();
};
}
template<typename T>
std::shared_ptr<T> Resolve() {
auto it = creators.find(std::type_index(typeid(T)));
if (it == creators.end()) {
return nullptr; // 未注册
}
return std::static_pointer_cast<T>(it->second());
}
private:
std::map<std::type_index, std::function<std::shared_ptr<void>()>> creators;
};
3. 使用示例:注入Logger到Service
定义接口和实现:
星辰Agent
科大讯飞推出的智能体Agent开发平台,助力开发者快速搭建生产级智能体
378
查看详情
struct ILogger {
virtual void log(const std::string& msg) = 0;
virtual ~ILogger() = default;
};
struct ConsoleLogger : ILogger {
void log(const std::string& msg) override {
std::cout << "[LOG] " << msg << std::endl;
}
};
struct FileLogger : ILogger {
void log(const std::string& msg) override {
std::cout << "[FILE] " << msg << std::endl; // 简化模拟
}
};
struct MyService {
std::shared_ptr<ILogger> logger;
MyService(std::shared_ptr<ILogger> l) : logger(l) {}
void doWork() {
logger->log("Doing work...");
}
};
主函数中使用容器:
int main() {
Container container;
container.Register<ILogger, ConsoleLogger>(); // 绑定接口到实现
container.Register<MyService, MyService>(); // 自注册
auto service = container.Resolve<MyService>();
if (service) {
service->doWork();
}
return 0;
}
输出结果:
[LOG] Doing work...
只需修改Register语句,就能切换成FileLogger,无需改动Service代码。
4. 进阶思路:支持构造函数自动解析
上面的例子中,MyService虽然用了依赖注入,但创建仍需手动处理。理想情况是容器能自动解析构造函数参数。
可通过以下方式增强:
- 为每个类注册工厂函数,捕获依赖项
- 利用C++20的反射或宏记录依赖关系(较复杂)
- 限制仅支持单一构造函数注入,简化逻辑
简单做法:显式注册带依赖的构造:
container.Register<MyService>([&]() {
return std::make_shared<MyService>(container.Resolve<ILogger>());
});
这样就实现了层级依赖的自动组装。
基本上就这些。C++没有运行时反射,所以DI容器比J*a/Spring简单得多,但也足够应对大多数场景。关键是理解:把“谁来创建对象”的权力交出去,就是控制反转的本质。
以上就是c++++如何实现一个简单的依赖注入容器_c++控制反转(IoC)原理的详细内容,更多请关注其它相关文章!
# 不需要
# hyein seo恶魔皮草
# 专业网站建设深圳
# 攀枝花seo优化电话
# 众筹的营销推广
# seo业绩表现
# SEO分析数据库
# 安阳抖音付费营销推广中心
# 网站医学推广禁止
# 枣庄网站建设总结怎么写
# 河南seo排名最便宜
# 是由
# java
# 抽象类
# 序列化
# 进阶
# 怎么处理
# 就能
# 是在
# 绑定
# 如何实现
# red
# c++
# ai
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
Yandex浏览器官方网页版入口 Yandex浏览器最新版官网
限制HTML日期输入框的日期选择范围
Win11文件资源管理器卡顿怎么修 Win11重置资源管理器进程优化响应速度【修复方法】
解决Python logging 中 datefmt 导致时间戳固定不变的问题
Word2013如何插入视频和音频媒体_Word2013媒体插入的多媒体支持
qq浏览器打开空白页怎么办 qq浏览器启动后显示白屏的解决教程
字由网在线版登录地址 字由网网页版安全入口
如何在CSS中使用浮动制作导航栏_float实现水平菜单
AO3最新入口2025公告_AO3中文官网合集
MinIO大规模对象列表性能瓶颈深度解析与外部元数据管理策略
解决深度学习模型训练初期异常高损失与完美验证准确率问题
PS5 Pro有点优势但不多! 《燕云十六声》PS5平台与PC性能画面对比
C++如何解决segmentation fault_C++段错误调试与原因分析
抖音从哪里进入网页版_抖音官方入口链接
蛙漫2日版入口 WAMAN2(日版)无删减漫画官网链接
在Go语言中利用后缀数组处理多字符串:实现高效文本匹配与自动补全
qq浏览器如何查看和导出已保存的密码 qq浏览器密码管理器数据备份教程
三星GalaxyZFold5怎样在相册制作折叠屏分镜_iPhone三星GalaxyZFold5相册制作折叠屏分镜【创意编辑】
word中如何让数字纵向排列_Word数字纵向排列方法
XML中包含HTML标签导致解析错误? 正确嵌入非XML数据的两种方法
微信网页版登录教程_微信网页版登录入口在哪
uc手机浏览器网页版入口 uc浏览器手机版便捷登录首页
iwriter统一登录平台 iwrite账号密码登录页面
纯CSS与HTML网格布局的HTML精简策略:SVG与JS方案解析
如何优雅地解决Livewire文件上传难题?SpatieLivewireFilepond让一切变得简单
韩小圈电脑版在线入口_网页版免费登录地址
C++ typeid如何获取类型信息_C++ RTTI运行时类型识别用法
如何使用Node.js csv 包按条件移除含空字段的CSV记录
优化MinIO list_objects_v2 操作的性能瓶颈与最佳实践
《刺客信条4:黑旗》重制版新细节曝光:无缝加载 地图更细致!
学习通在线学习平台 学习通网页版直接进入课程中心
拼多多视频播放卡顿如何处理 拼多多视频播放优化技巧
Yandex官网免登录入口_俄罗斯Yandex搜索引擎一键访问
解决macOS Tkinter应用双击启动崩溃:PyInstaller打包指南
QQ邮箱官方邮箱登录入口 QQ邮箱网页版快速访问
steam官方入口大全 steam账号注册及操作指南
Log4j Console Appender性能瓶颈与高并发优化策略
J*a TimerTask中HashMap意外清空的深层原因与解决方案
Win11蓝牙耳机断连怎么解决 Win11蓝牙设置重新配对与驱动更新【技巧】
Golang如何通过reflect操作map_Golang reflect map操作与遍历技巧
Tailwind CSS line-clamp 布局问题解析与修复指南
在Qt QML中通过Python字典动态更新TextEdit内容的教程
Django AJAX 文件上传教程:解决图片无法保存到模型的常见问题
如何创建没有密码的Windows本地账户_跳过微软账户登录的技巧【教程】
妖精动漫免费平台 妖精动漫官网资源观看网址
在React函数组件中利用原生HTML5进行邮箱地址验证
Lar*el如何正确地在控制器和模型之间分配逻辑_Lar*el代码职责分离与架构建议
win11 arm版怎么安装 M1/M2 Mac虚拟机安装ARM win11的方法
Lar*el表单中优雅地处理“返回”按钮以规避验证:最佳实践指南
Excel函数批量查找替换超快方法_Excel用REPLACE和FIND函数秒级替换


2025-12-05
浏览次数:次
返回列表