Ответ в теме: Опережающее объявление класса

      Комментарии к записи Ответ в теме: Опережающее объявление класса отключены
#3042

Прием, используемый в этом примере называется предварительным (опережающим) объявлением класса (forward reference class). Такое объявление помогает решить, как минимум, две проблемы:

1 Ослабить зависимости между файлами, сократить время компиляции

Директива #include говорит компилятору, что он должен включить код одного файла в другой файл. Это сложная операция, которая может занимать много времени. С другой стороны, допустим, мы изменили что-либо в классе — при следующей компиляции проекта будут перекомпилированы все файлы, в которые включался "server.h". В больших проектах такая компиляция может заниматься несколько часов.
В ряде случаев компиляции всех файлов, использующих изменяемый класс можно избежать. Посмотрите на класс Server — он содержит указатель на класс QTcpServer, т.е. вне зависимости от того, как реализован QTcpServer, наш класс будет содержать, скажем, 4 байта с адресом объекта. Во всех таких случаях мы можем (нам следует) не включать заголовочный файл целиком, а лишь указать компилятору, что такой класс есть в нашей программе при помощи опережающего объявления. Это же относится к списку указателей — QList<ISocketAdapter*>, а также к всем случаям, когда класс содержит (или его функция принимает в качестве аргументов) указатель или ссылку на объект.
В связи с этим, Скотт Мэйерс рекомендует избегать использования объектов, если можно обойтись ссылками или указателями. Однако, надо помнить, что использование объектов в классе, в отличии от указателей, безопасно с точки зрения исключений — поэтому чтобы ослабить зависимости и при этом не получить проблем с исключениями — используйте какой-либо вид умных указателей.

2 Разорвать циклические зависимости классов

Допустим, у нас получилась следующая ситуация:

// файл foo.h
#include "bar.h"
class Foo {
Bar bar;
};
// файл bar.h
#include "foo.h"
class Bar {
f(Foo foo);
};

Ситуация безусловно не самая лучшая, однако ее вариации иногда встречаются на практике — зависимости между файлами могут создаваться аргументами функций-членов. Компилятор не сможет обработать эти файлы, т.к. между ними есть циклические зависимости. Значит, нам надо ослабить эти зависимости, например так:

// файл foo.h
#include "bar.h"
class Foo {
Bar bar;
};
// файл bar.h
class Foo;
class Bar {
f(const Foo &foo);
}

Рекомендую прочитать подробнее про указатели и ссылки — ведь с их помощью можно не только ослабить зависимости, но и повысить гибкость. Кроме того, использование объектов-членов в классах нарушает принцип инверсии зависимостей (DIP — Dependency Inversion Principle).