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.