class A {
B x;
};
class B {
A x;
};
The compiler tells me that B
is not a type.
class A {
B x;
};
class B {
A x;
};
The compiler tells me that B
is not a type.
It can. But what you are trying to do is clearly wrong, and there is no way to preclear the classes so that your code works.
The compiler must know the size of all types used. And we see your problem: The class A
contains an instance of the class B
, which contains an instance of class A
, which contains an instance of the class B
, which contains ...
To make your code work, you have to change the definition of at least one of the classes. So, instead of using one full instance of the other, use a pointer :
class B;
class A {
B *b;
};
class B {
A a;
};
You have already seen how a class is predefined : class B;
. But by pre-clearing it, we can only work with pointers and references to it: as we said before, the compiler needs to know the size strong>. When we preclear it, we are not reporting the actual size of the class ... but the size of a pointer to our class is known at all times.
There is little to add to the response of Trauma , you have explained perfectly that you can not define an object in C ++ without knowing the size of it. I would like to add a possible solution to the problem you pose:
The implementation in pointer (known as pImpl in English) is a design pattern that separates the implementation details of an object from its representation by placing them in a separate object accessed through a pointer:
class pImplA;
class pImplB;
class A
{
pImplA *pA{nullptr};
public:
A();
~A() { delete pA; }
};
class B
{
pImplB *pB{nullptr};
public:
B();
~B() { delete pB; }
};
The pointers pImplA
and pImplB
are the ones that point to the actual implementation, which should be defined later:
class pImplA
{
B x;
};
class pImplB
{
A x;
};
To finish, you have to define (in a code file, not a header) the constructors of A
and B
:
A::A() : pA{new pImplA}{}
B::B() : pB{new pImplB}{}
Be careful, as the code is defined, it will create a recursive loop of A
creating B
creating A
creating B
creating A
... but I understand that in a real implementation it will not be the case, because your code was only illustrative, right?