Home > Net >  C dependency injection through constructor
C dependency injection through constructor

Time:07-29

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?

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

CodePudding user response:

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.

  •  Tags:  
  • c
  • Related