Заголовочные файлы
надо писать так, чтобы порядок их подключения был неважен.
В реализации подключать первым собственный заголовочник — правильная идея; так мы убеждаемся, что в заголовочнике нет недостающих зависимостей.
Совать #include в пространство имён без хорошего обоснования не стоит.
По вашему обтекаемому описанию не видно, как устроены ваши заголовки, именованное пространство имён или нет, закрыты ли все скобки в хедерах, и т.д. Но причина ошибки очевидна: из-за пространств имён компилятор не отождествил классы в первом и втором заголовке; предварительное объявление «class A;» осталось неразрешённым. Поэкспериментировав, я выяснил вот что.
// Не компилируется!
class A;
namespace XXX {
std::shared_ptr<A> a;
class A { public: int x; };
void xxx();
}
void XXX::xxx() {
a->x;
}
// Компилируется!
class A;
namespace XXX {
class A { public: int x; };
std::shared_ptr<A> a;
void xxx();
}
void XXX::xxx() {
a->x;
}
// Тоже компилируется!
namespace XXX {
class A;
}
namespace XXX {
std::shared_ptr<A> a;
class A { public: int x; };
void xxx();
}
void XXX::xxx() {
a->x;
}
В первом случае
shared_ptr<::A>
, который, естественно, не определён (есть
XXX::A
).
Во втором — определение наперёд ::A вообще ни на что не сдалось; используется
shared_ptr<XXX::A>
.
В третьем примере только один тип, XXX::A.
Если первым идёт не использование, а make_shared — выходит другая ошибка, не удаётся получить sizeof недоопределённого типа A.