У каждого класса не может быть "поля другого типа"; это было бы рекурсивным определением, и не только компилятор не смог бы извлечь из него никакого смысла, он даже не имеет логического смысла.
Каждый класс, имеющий поле, являющееся типом другого класса, является видом невозможности, который вы видите только в M.C. Рисунки Эшера или их анимации, например:
Источник: escherdroste.math.leidenuniv.nl
на основе литографии Эшера "Галерея печати", 1956 г., см. Википедию
Одно из двух полей должно быть указателем , чтобы нарушить рекурсивное удержание и избежать логической невозможности.
Что приводит нас к следующей проблеме: если класс B должен содержать экземпляр класса A, то, очевидно, A должен быть объявлен перед классом B, так что A уже известен компилятору при компиляции B. Но если класс A объявлен перед классом B, как мы можем объявить указатель на B в A? Класс B еще не известен во время компиляции A! Ответом на это является специальная конструкция, известная как предварительное объявление , которая существует именно для того, чтобы приспособиться к подобным ситуациям. Предварительное объявление класса B выглядит следующим образом:
class B;
Все, что говорит компилятору, - это то, что будет класс с именем B. Он ничего не говорит компилятору о содержимом класса B, поэтому мы мало что можем с ним сделать, но мы можем сделать одну вещь : объявить указатели на B.
Итак, полное решение проблемы выглядит так:
файл "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 been defined yet.
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;
}
файл "Б.ч":
#include "A.h"
class B
{
/* the compiler now knows the size of "A", so we can have a field of type "A". */
A a;
}