Вы должны избегать циклических зависимостей. Одним из распространенных способов избежать их является предварительное объявление типа и отсутствие в заголовке каких-либо экземпляров или вызовов функций этого типа.
Это делается путем изменения экземпляров, таких как B b
, в ссылки. или указатели: B* b
. Вы также должны переместить любой код, который использует b
, в файл CPP, чтобы вы могли #include "B.h"
до его использования.
Например, вместо
// we'll remove this header's dependency on B shortly
#include "B.h"
class A
{
B b;
public:
A() { b.SetInt(0); }
};
Вы делаете что-то вроде этого:
class B;
class A
{
B *b; // *pointers and &references to a predeclared class are fine.
public:
A();
~A();
};
... и затем в A. cpp:
#include "A.h" // ALWAYS include your own header first
#include "B.h"
A::A()
{
// we didn't need to know how big B was until now, when we're about to make one and
// run its constructor. We'll also need to know what functions are available, and the
// types of all its parameters (or lack of parameters).
b = new B();
b->SetInt(0);
}
A::~A()
{
delete b; // for every "new" there must be a "delete"
}
Да, это было бы (намного) лучше с std::unique_ptr<B> b
вместо необработанного указателя. С умным указателем нам не нужен явный деструктор. Я просто не хотел бросать слишком много потенциально новых вещей в кого-то, кто еще учится.
В качестве альтернативы, вы можете передать ссылку в конструктор и использовать список инициализатора члена (вы можете устанавливать ссылки только тогда, когда они ' перестроен). Это вызывает проблемы с «продолжительностью жизни объекта». Если экземпляр B, который вы передадите во время строительства, будет уничтожен до того, как с ним будет завершен A, ваша программа будет жестоко взламывать sh (если вам повезет: таким образом, у вас будет хорошее представление о том, в чем проблема это) в следующий раз, когда он используется. Лучше всего избегать этого, пока у вас не будет значительно больше опыта под вашим поясом.