Abhängigkeitsinjektion (Dependency Injection) in C++: Container und Praxis

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Dependency Injection Container für C++: Überblick und praktische Beispiele

\n\n

In der modernen C++-Entwicklung werden zunehmend die Prinzipien Inversion of Control (IoC) und Dependency Injection (DI) angewendet. Diese Entwurfsmuster ermöglichen die Erstellung von lose gekoppeltem, testbarem und leicht erweiterbarem Code. Im Gegensatz zu Sprachen mit verwalteter Speicherverwaltung (Java, C#) verfügt C++ nicht über eine eingebaute Reflexion, daher erfordert die Implementierung von DI-Containern hier Template-Metaprogrammierung und die Verwendung moderner Standards (C++11/14/17/20).

\n\n

In diesem Artikel betrachten wir drei gängige Ansätze zur Abhängigkeitsinjektion in C++: die Bibliotheken Boost.DI, Google Fruit und Kangaru, und schreiben zum Verständnis der Mechanik auch einen eigenen einfachen Container.

\n\n

Was ist Dependency Injection?

\n\n

Dependency Injection ist eine Technik, bei der ein Objekt seine Abhängigkeiten von außen erhält, anstatt sie selbst zu erstellen. Die wichtigsten Arten von DI sind:

\n
    \n
  • Constructor Injection – Abhängigkeiten werden über den Konstruktor übergeben.
  • \n
  • Setter Injection – Abhängigkeiten werden über Setter gesetzt.
  • \n
  • Interface Injection – Abhängigkeiten werden über eine Schnittstelle übergeben.
  • \n
\n\n

Beispiel ohne DI (feste Kopplung):

\n
class Logger {\npublic:\n    void log(const std::string& msg) { /* Schreiben in Datei */ }\n};\n\nclass Service {\n    Logger logger; // Feste Abhängigkeit\npublic:\n    void doWork() { logger.log("Arbeit erledigt"); }\n};
\n\n

Beispiel mit DI (lose Kopplung):

\n
class ILogger {\npublic:\n    virtual ~ILogger() = default;\n    virtual void log(const std::string& msg) = 0;\n};\n\nclass ConsoleLogger : public ILogger {\npublic:\n    void log(const std::string& msg) override { std::cout << msg << std::endl; }\n};\n\nclass Service {\n    std::shared_ptr<ILogger> logger;\npublic:\n    explicit Service(std::shared_ptr<ILogger> l) : logger(std::move(l)) {}\n    void doWork() { logger->log("Arbeit erledigt"); }\n};
\n\n

Überblick über DI-Container für C++

\n\n

1. Boost.DI

\n

Boost.DI ist eine der beliebtesten Bibliotheken. Sie verwendet C++14/17-Templates zur automatischen Auflösung von Abhängigkeiten. Unterstützt Polymorphie, Gültigkeitsbereiche (Singleton, Unique) und modulare Konfiguration.

\n\n

Anwendungsbeispiel:

\n
#include <boost/di.hpp>\n#include <iostream>\n\nnamespace di = boost::di;\n\nclass IWriter {\npublic:\n    virtual ~IWriter() = default;\n    virtual void write(const std::string&) = 0;\n};\n\nclass ConsoleWriter : public IWriter {\npublic:\n    void write(const std::string& msg) override {\n        std::cout << msg << std::endl;\n    }\n};\n\nclass App {\n    std::shared_ptr<IWriter> writer;\npublic:\n    explicit App(std::shared_ptr<IWriter> w) : writer(std::move(w)) {}\n    void run() { writer->write("Hallo von Boost.DI!"); }\n};\n\nint main() {\n    auto injector = di::make_injector(\n        di::bind<IWriter>.to<ConsoleWriter>()\n    );\n    auto app = injector.create<std::unique_ptr<App>>();\n    app->run();\n    return 0;\n}
\n\n

Vorteile: starke Typisierung, minimaler Laufzeit-Overhead, Unterstützung von C++14/17.

\n

Nachteile: komplexe Compiler-Fehlermeldungen, längere Build-Zeiten.

\n\n

2. Google Fruit

\n

Google Fruit ist ein Container von Google, der auf C++11 basiert. Verwendet Makros zur Registrierung von Komponenten und unterstützt die Injektion über den Konstruktor.

\n\n

Beispiel:

\n
#include <fruit/fruit.h>\n#include <iostream>\n\nclass IWriter {\npublic:\n    virtual void write(const std::string&) = 0;\n};\n\nclass ConsoleWriter : public IWriter {\npubli                    

Empfehlungen