Última atualização:2026-10-12
Injeção de dependência em C++¶
Ultimamente, um colega da comunidade pediu para atualizar o tema injeção de dependência, então escrevi este artigo, explicando a partir de exemplos práticos; o texto cobre alguns princípios e implementações, e a versão completa do código está disponível na comunidade. Vamos ao texto.
Roteiro:
- dependência direta
- injeção de dependência por interface
- injeção de dependência por template
A injeção de dependência é um design pattern muito usado; normalmente adota-se a abordagem por interface/template para melhorar a testabilidade e a manutenibilidade do código. Vejamos um exemplo.
Suponha que haja uma classe de serviço de usuário, UserService, que precisa se comunicar com um servidor remoto por meio de um cliente HTTP; nesse caso, poderíamos escrever as três implementações a seguir.
1. Dependência direta¶
UserService depende diretamente de HttpClient internamente; por exemplo:
class HttpClient {
public:
std::string Get(const std::string& url);
void Post(const std::string& url, const std::string& data);
};
class UserService {
private:
HttpClient m_httpClient;
};
Dentro de UserService geralmente haveria alguns métodos para operar m_httpClient; essa abordagem é simples e direta, mas acopla UserService a um HttpClient concreto, o que torna difícil substituir o objeto de dependência e difícil fazer testes de unidade.
Daí surgem os dois métodos a seguir.
2. Injeção de dependência por interface¶
Nosso objetivo é que o teste seja conveniente, sem a necessidade de criar uma classe concreta — o usuário pode criar por mock uma classe para testar; então lembramos das interfaces: extraímos HttpClient e obtemos:
struct IHttpClient {
virtual std::string Get(const std::string& url) = 0;
virtual void Post(const std::string& url, const std::string& data) = 0;
virtual ~IHttpClient() = default;
};
class UserService {
private:
std::unique_ptr<IHttpClient> m_httpClient;
};
Assim, no momento do teste, pode-se criar por mock um client para testar; por exemplo:
class MockHttpClient : public IHttpClient {
public:
MOCK_METHOD(std::string, Get, (const std::string& url), (override));
MOCK_METHOD(void, Post, (const std::string& url, const std::string& data), (override));
};
auto mockHttpClient = std::make_unique<MockHttpClient>();
UserService userService(std::move(mockHttpClient));
Após essa transformação, conseguimos:
- esconder os detalhes de implementação no arquivo .cc
- trabalhar com interfaces abstratas
- injetar as dependências durante a construção do objeto
3. Injeção de dependência por template¶
A injeção de dependência por template usa a técnica de templates de C++ para passar o objeto de dependência como parâmetro de template a UserService. Ao instanciar o template, especifica-se a implementação concreta do cliente HTTP. Esse método resolve a dependência em tempo de compilação, sem chamadas de funções virtuais, melhorando o desempenho. Ao mesmo tempo, permite que a classe UserService se integre de forma flexível com diferentes implementações de cliente HTTP e facilita os testes de unidade.
Nesse caso, é bem fácil testar; por exemplo:
Essa abordagem traz os seguintes benefícios:
- injetar as dependências durante a instanciação do template
- sem chamadas virtuais (note que THttpClient não é uma interface, de modo que as chamadas podem ser resolvidas em tempo de compilação)
Este é todo o conteúdo desta seção; o código completo está na comunidade — assine e baixe!
Tópicos relacionados¶
- C++ evitar o construtor padrão | C++那些事
- Idiom de lista de inicialização de classes em C++ | C++那些事
- C++: templates de classe em vez de templates de função | C++那些事
- Idiom copy-and-swap em C++ | C++那些事
- C++ enum class enumerações fortemente tipadas | C++那些事
- C++ Header-Only versus separação de implementação | C++那些事
- Idiom de avaliação preguiçosa em C++ | C++那些事
- Idiom de consulta em tabela em C++ | C++那些事
- Ponteiros para membros e type info em C++ | C++那些事
- Idiom Mixin em C++ | C++那些事