Injeção de Dependência (Dependency Injection) em C++: contêineres e prática

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Contêiner de Dependency Injection para C++: visão geral e exemplos práticos



No desenvolvimento moderno em C++, os princípios de Inversion of Control (IoC) e Dependency Injection (DI) são cada vez mais aplicados. Esses padrões permitem criar código fracamente acoplado, testável e facilmente extensível. Ao contrário de linguagens com gerenciamento de memória (Java, C#), C++ não possui reflexão embutida, portanto, a implementação de contêineres DI aqui requer metaprogramação de modelos e o uso de padrões modernos (C++11/14/17/20).



Neste artigo, examinaremos três abordagens populares para injeção de dependência em C++: as bibliotecas Boost.DI, Google Fruit e Kangaru, além de escrever nosso próprio contêiner simples para entender a mecânica.



O que é Dependency Injection?



Dependency Injection é uma técnica na qual um objeto recebe suas dependências externamente, em vez de criá-las ele mesmo. Os principais tipos de DI são:

  • Constructor Injection — as dependências são passadas através do construtor.
  • Setter Injection — as dependências são definidas através de setters.
  • Interface Injection — as dependências são passadas através de uma interface.


Exemplo sem DI (acoplamento rígido):

class Logger {public:    void log(const std::string& msg) { /* gravação em arquivo */ }};

class Service { Logger logger; // Dependência rígidapublic: void doWork() { logger.log("Work done"); }};


Exemplo com DI (acoplamento fraco):

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"); }};


Visão geral dos contêineres DI para C++



1. Boost.DI

Boost.DI — uma das bibliotecas mais populares. Ela usa modelos C++14/17 para resolução automática de dependências. Suporta polimorfismo, escopos (singleton, unique) e configuração modular.



Exemplo de uso:

#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;}


Prós: tipagem forte, overhead mínimo em tempo de execução, suporte a C++14/17.

Contras: mensagens de erro de compilação complexas, aumento do tempo de compilação.



2. Google Fruit

Google Fruit — contêiner do Google, funcionando em C++11. Usa macros para registrar componentes e suporta injeção via construtor.



Exemplo:

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

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

class ConsoleWriter : public IWriter {publi

Recommendations