Объявление вперед включает, помимо объявления include (ClassFwd.h + Class.h)
В Effective С++ (3-е издание) Скотт Мейерс в пункте 31 предполагает, что классы должны иметь, помимо своих классических файлов декларации (.h) и определения (.cpp), файл декларации Forward Forward Include File (fwd. h), какой класс, который не нуждается в полном определении, может использовать, а не наоборот, объявляя себя.
Я кое-что вижу в этом случае, но я действительно не вижу в этом жизнеспособного варианта... Кажется, очень сложно поддерживать, а скорее излишне и вряд ли необходимо.
Я могу, однако, увидеть его использование для форвардных деклараций шаблонов, которые довольно тяжелы. Но для простых классов? Похоже, что это боль для поддержания и создания множества почти пустых файлов, которые служат очень маленькой цели... стоит ли хлопот?
Вот пример:
// Class.h
class Class
{
Class();
~Class();
};
// ClassFwd.h
class Class;
// Class.cpp
Class::Class()
{
}
Class::~Class()
{
}
Мой вопрос:
Что вы, ребята, думаете? Если это хорошая практика?
ПРИМЕЧАНИЕ Меня больше интересуют аргументы для этой практики, чтобы увидеть, пропустил ли я что-то, что позволило бы мне согласиться с Скоттом Мейерсом.
Ответы
Ответ 1
Я использовал файлы заголовков деклараций для всех моих библиотек. Обычно библиотека имеет такую структуру:
lib/
include/
class headers + Fwd.h
src/
source files + internal headers
Каталог lib/include
будет содержать все заголовки общих классов вместе с одним заголовком форвардных объявлений. Это сделало библиотеку легкой на стороне включения. Любой заголовок вне этой библиотеки включает только прямой заголовок (Fwd.h
), а источники за пределами этой библиотеки содержат необходимые полные заголовки. Можно также предоставить заголовок удобства (Lib.h
), который включает все остальные заголовки, для использования в исходных файлах.
Еще одна вещь, которую нужно поместить в заголовок прямой декларации, - typedef
для shared_ptr
, особенно в случае иерархии наследования с классами factory, которые возвращают указатели на реализации.
Вышеприведенное полезно для больших приложений с большим количеством внутренних библиотек. Уточнение вышеприведенного для этого случая было бы поместить публичные заголовки в lib/include/lib
. Таким образом, клиенты вашей библиотеки должны будут включать lib/...
. Подумайте об этом как о пространстве имен для ваших заголовков.
Удачи!
Ответ 2
Размещение простого class Whatever;
в собственном заголовке не имеет преимуществ и большого количества недостатков.
Особенно в случае, когда доступ к заголовку может занять много времени, в нем используются простые форвардные объявления, чтобы избежать доступа к заголовкам; помещая их в свои собственные заголовки, победит цель...
С шаблонами, как вы заметили, это другое дело. Например. проверьте <iosfwd>
из стандартной библиотеки.
Приветствия и hth.
Ответ 3
Практика позволяет пользователю кода не думать о том, является ли класс регулярным или шаблонным. Пользователь просто # включает файл "соответствующий_fwd.h" и имеет ссылку на класс. Еще одно раздражение для пользователя - это хорошая вещь. Но если это небольшой проект или создатель класса является единственным пользователем класса, тогда это может быть более раздражающим. Таким образом, это зависит.
Ответ 4
Если у вас есть большое решение, это ваш единственный шанс обработать неотъемлемые зависимости:
struct A {
B* m_pB;
};
struct B {
A* m_pA;
};
Теперь A и B могут быть в разных заголовочных файлах, возможно, даже в разных проектах. Тем не менее, их зависимость - это не какой-то дефект дизайна, а вполне логичный и необходимый. Чем ты занимаешься?
- Сначала включите один заголовок Forward.h для заголовка. для требуемого проекта eeach, т.е. в прямом объявлении нет собственного файла заголовка для каждого класса.
- Затем включите Class.h всех необходимых проектов. Для этих заголовков потребуются форвардные декларации для компиляции.
- Включить заголовки основного проекта.
В довольно большом решении (500K LOC) я нашел этот шаблон очень легко управляемым. В противном случае, если вы измените объявление класса, где вы найдете все объявления вперед, которые могут быть сделаны индивидуально в любом количестве других файлов заголовков?