C++中的依赖注入(Dependency Injection):容器与实践

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++依赖注入容器:概述与实践示例



在现代C++开发中,控制反转(IoC)和依赖注入(DI)原则的应用越来越广泛。这些模式有助于创建低耦合、可测试且易于扩展的代码。与具有托管内存的语言(Java、C#)不同,C++没有内置的反射机制,因此在此实现DI容器需要模板元编程并利用现代标准(C++11/14/17/20)。



在本文中,我们将探讨C++中依赖注入的三种流行方法:Boost.DI、Google Fruit和Kangaru库,并编写一个简单的自定义容器以理解其机制。



什么是依赖注入?



依赖注入是一种技术,对象从外部获取其依赖项,而不是自行创建。主要的DI类型包括:

  • 构造函数注入 —— 依赖项通过构造函数传递。
  • Setter注入 —— 依赖项通过setter方法设置。
  • 接口注入 —— 依赖项通过接口传递。


无DI示例(紧耦合):

class Logger {public:    void log(const std::string& msg) { /* 写入文件 */ }};

class Service { Logger logger; // 紧耦合依赖public: void doWork() { logger.log("Work done"); }};


使用DI示例(松耦合):

class ILogger {public:    virtual ~ILogger() = default;    virtual void log(const std::string& msg) = 0;};

class ConsoleLogger : public ILogger {public: void log(const std::string& msg) override { std::cout << msg << std::endl; }};

class Service { std::shared_ptr<ILogger> logger;public: explicit Service(std::shared_ptr<ILogger> l) : logger(std::move(l)) {} void doWork() { logger->log("Work done"); }};


C++ DI容器概述



1. Boost.DI

Boost.DI —— 最流行的库之一。它利用C++14/17模板自动解析依赖关系。支持多态、作用域(单例、唯一)和模块化配置。



使用示例:

#include <boost/di.hpp>#include <iostream>

namespace di = boost::di;

class IWriter {public: virtual ~IWriter() = default; virtual void write(const std::string&) = 0;};

class ConsoleWriter : public IWriter {public: void write(const std::string& msg) override { std::cout << msg << std::endl; }};

class App { std::shared_ptr<IWriter> writer;public: explicit App(std::shared_ptr<IWriter> w) : writer(std::move(w)) {} void run() { writer->write("Hello from Boost.DI!"); }};

int main() { auto injector = di::make_injector( di::bind<IWriter>.to<ConsoleWriter>() ); auto app = injector.create<std::unique_ptr<App>>(); app->run(); return 0;}


优点:强类型,最小运行时开销,支持C++14/17。

缺点:编译错误信息复杂,构建时间增加。



2. Google Fruit

Google Fruit —— 来自Google的容器,基于C++11。使用宏注册组件,并支持通过构造函数注入。



示例:

#include <fruit/fruit.h>#include <iostream>

class IWriter {public: virtual void write(const std::string&) = 0;};

class ConsoleWriter : public IWriter {publi

推荐