Il n'est pas possible que chaque classe ait "un champ qui est le type d'une autre classe" ; il s'agirait d'une définition récursive et non seulement le compilateur ne serait pas en mesure d'en tirer le moindre sens, mais cela n'aurait même pas de sens sur le plan logique.
Chaque classe ayant un champ qui est un type de l'autre classe est le genre d'impossibilité que l'on ne voit que dans les dessins de M.C. Escher, ou dans les animations de ceux-ci, comme celle-ci :
B. de Smit et H. W. Lenstra - Source : escherdroste.math.leidenuniv.nl
d'après la lithographie "Print Gallery" d'Escher, 1956, voir Wikipédia
L'un des deux champs doit être un pointeur afin de briser le confinement récursif et d'éviter l'impossibilité logique.
Ce qui nous amène au problème suivant : si la classe B doit contenir une instance de la classe A, il est évident que A doit être déclarée avant la classe B, de sorte que A soit déjà connu du compilateur lors de la compilation de B. Mais si la classe A est déclarée avant la classe B, comment pouvons-nous déclarer un pointeur sur B dans A ? La classe B n'est pas encore connue au moment où A est compilée ! La réponse à cette question est une construction spéciale connue sous le nom de déclaration préalable qui existe précisément pour répondre à des situations comme celle-ci. Une déclaration préalable de classe B se présente comme suit :
class B;
Tout ce qu'il dit au compilateur, c'est qu'il y aura une classe appelée B. Il ne dit rien au compilateur sur le contenu de la classe B, donc il y a très peu de choses que nous pouvons faire avec, mais nous pouvons faire une chose : déclarent des pointeurs sur B.
La solution complète du problème se présente donc comme suit :
fichier "A.h" :
/* This is called a "forward declaration". We use it to tell the compiler that
the identifier "B" will from now on stand for a class, and this class will be
defined later. We will not be able to make any use of "B" before it has been
defined, but we will at least be able to declare pointers to it. */
class B;
class A
{
/* We cannot have a field of type "B" here, because it has not yet been
defined. However, with the forward declaration we have told the compiler
that "B" is a class, so we can at least have a field which is a pointer
to "B". */
B* pb;
}
fichier "B.h" :
#include "A.h"
class B
{
/* the compiler now knows the size of "A", so we can have a field
of type "A". */
A a;
}