Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ dependency injection through constructor

I tried making a simple DI test, where a class car is injected with a container interface.

It gives an error ‘incomplete type’, see the comment in the code.

What am I doing wrong?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#include <iostream>
#include <string>

class Car;

class IContainer {
public:
    virtual ~IContainer()=default;
};

class Container: public IContainer {
public:
    explicit Container(int i = 1) {
        std::cout << std::to_string(i);
    };

    void makeCar() {
        Car car(this); //Variable has incomplete type 'Car'
    }
};


class Car  {
public:
    explicit Car(IContainer &container): c(container) {
        printf("constructed\n");
    }

private:
    IContainer &c;
};


int main() {

    Container container(5);
    container.makeCar();

    return 0;
}

Solution – here’s the working modified code:

#include <iostream>
#include <string>

class Car;

class IContainer {
public:
    virtual ~IContainer()=default;
    virtual void foo(){}
};

class Container: public IContainer {
public:
    explicit Container(int i = 1) {
        std::cout << std::to_string(i) << std::endl;
    };

    void foo() override {
        std::cout << "bar\n";
    }

    void makeCar();

};


class Car  {
public:
    explicit Car(IContainer *container): c(container) {
        printf("Car constructed\n");
        c->foo();
    }

private:
    IContainer *c;
};

void Container::makeCar() {
    //Constructing the car will call a function on the injected container
    Car car(this);
}

int main() {

    Container container(5);
    container.makeCar();

    return 0;
}

>Solution :

Your C++ compiler reads your C++ program from beginning to the end, compiling as it goes along. At any point your C++ compiler only knows what it’s read so far (we’ll ignore some specific exceptions that do not matter here).

class Car;

Your C++ compiler now knows that your program has a class named Car. It doesn’t know anything at all about this class. Nothing. Zilch. Nada. Zippo.

    void makeCar()
    {
        Car car(this);
    }

Now your C++ compiler needs to generate code that creates such a Car. That’s a problem: your C++ compiler doesn’t know anything at all about this class. Nothing. Zilch. Nada. Zippo.

The complete class gets declared later, but your C++ compiler doesn’t know anything about it.

The solution is simple: just declare the class method here:

    void makeCar();

And then later, after Car is declared, you can define this class method (just before main):

void Container::makeCar() {
    Car car(this); // It works!
}

Everything else remains the same. Now your C++ compiler is omnipotent, all-knowing, and all-powerful. It knows everything now.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading