2010-10-14 2 views
10

В Эффективном C++ (3-е издание) Скотт Мейерс в пункте 31 предполагает, что классы должны иметь, помимо своей классической Декларации (. h) и определения (.cpp), файл декларации Forward Forward Include (fwd.h), который может не использоваться для полного определения, а не для объявления вперед.Вперед декларация включает, помимо объявления включить (ClassFwd.h + Class.h)

Я немного смотрю на это дело, но я действительно не вижу в этом жизнеспособного варианта ... Кажется, очень трудно поддерживать, а скорее излишне и вряд ли нужно.

Я могу, однако, увидеть его использование для форвардных объявлений шаблонов, которые довольно тяжелые. Но для простых классов? Похоже, что это боль в обслуживании и создаст много почти пустых файлов, которые служат очень маленькой цели ... стоит ли хлопот?

Вот пример:

// Class.h 
class Class 
{ 
    Class(); 
    ~Class(); 
}; 

// ClassFwd.h 
class Class; 

// Class.cpp 
Class::Class() 
{ 
} 

Class::~Class() 
{ 
} 

Мой вопрос:

Что вы думаете, ребята? Если это хорошая практика?

ПРИМЕЧАНИЕ Меня больше интересуют аргументы. Для этой практики, чтобы увидеть, пропустил ли я что-то, что позволило бы мне согласиться с Скоттом Мейерсом.

ответ

6

Я использовал вперед файлы заголовки декларации для всех моих библиотек библиотеки, как правило, имеет такую ​​структуру:..

lib/ 
    include/ 
    class headers + Fwd.h 
src/ 
    source files + internal headers 

каталог lib/include будет содержать все общественные классы заголовков вместе с заголовком одной декларации вперед Это сделало библиотеку свето- вес на стороне включения. Любой заголовок за пределами этой библиотеки включает только прямой заголовок (Fwd.h), а источники за пределами этой библиотеки включают в себя необходимое co mplete headers. Можно также предоставить заголовок удобства (Lib.h), который включает в себя все остальные заголовки для использования в исходных файлах.

Другая вещь, которую нужно поместить в заголовок прямой декларации, - typedef s для shared_ptr, особенно в случае иерархии наследования с фабричными классами, возвращающими указатели на реализации.

Вышеупомянутый полезен для больших приложений с большим количеством внутренних библиотек. Уточнение вышеприведенного для этого случая было бы разместить публичные заголовки в lib/include/lib. Таким образом, клиенты вашей библиотеки должны будут включать lib/.... Подумайте об этом как о пространстве имен для ваших заголовков.

Удачи вам!

+1

Спасибо за ответ, однако, вы просто заявляете, что делаете, а не почему вы это делаете. Единственный аргумент, который вы предоставляете, - это shared_ptr, который я уже решил, имея макрос FORWARD_SHARED(), который автоматически объявляет класс и его указатель автоматически. Это очень легкий и легкий для чтения ... – Geeho

+0

Хорошо, причина заключается в сокращении времени компиляции и централизации форвардных объявлений. Если все форвардные объявления находятся в одном файле, при добавлении новых классов легко добавлять новые. То же самое с указателем typedefs. Почему сокращение времени компиляции должно быть очевидным. Это имеет смысл для вас? Хранение файлов заголовков чистым от чего угодно, но форвардные объявления помогут, поскольку ваша кодовая база становится больше. –

+2

Ах! Итак, у вас есть один файл Fwd.h! Не один за заголовок! Теперь я вижу, как это может иметь смысл ... Хорошо, подумай об этом некоторое время ... – Geeho

0

Если у вас есть большое решение, это ваш единственный шанс справиться с присущими зависимости:

struct A { 
    B* m_pB; 
}; 

struct B { 
    A* m_pA; 
}; 

Теперь А и В может быть разумно в различных файлах, может быть, даже различные проекты. Тем не менее, их зависимость - это не какой-то дефект дизайна, а вполне логичный и необходимый. Чем ты занимаешься?

  1. Сначала включите один заголовок Forward.h для заголовка. Для требуемого проекта eeach, т. Е. В декларации forward нет собственного файла заголовка для каждого класса.
  2. Затем включите класс.h всех необходимых проектов. Для этих заголовков потребуются форвардные декларации для компиляции.
  3. Включите заголовки основного проекта.

В довольно большом решении (500k LOC) я нашел этот шаблон очень легко управляемым. В противном случае, если вы измените объявление класса, где вы найдете все объявления вперед, которые могут быть сделаны отдельно в любом количестве других файлов заголовков?

+0

Вы, например, похожи на случай для декларации в целом, а не для файлов fwd.h в частности. – Geeho

2

Размещение простого class Whatever; в его собственном заголовке не имеет преимуществ и множества недостатков.

Специально в случае, когда доступ к заголовку может занять много времени, в нем используются простые форвардные объявления, чтобы избежать доступа к заголовкам; помещая их в свои заголовки, победит цель ...

С шаблонами, как вы заметили, это другое дело. Например. проверьте <iosfwd> из стандартной библиотеки.

Cheers & hth.

+0

Моя проблема в том, что я согласен с тобой, но не с Мейерсом. Мог бы быть ответом, который я ищу, но я хочу, чтобы мое мнение оспаривалось! : D – Geeho

+0

С современным кэшированием дисков время компиляции (и памяти), попадающее в доступ к заголовку, не столько основано на количестве заголовков, сколько на сложности кода внутри. Тогда включение гораздо более простого заголовка вместо полного определения не нарушает цели вообще. –

+0

@BenVoigt: re "Включая гораздо более простой заголовок вместо полного определения", вопрос: * включая заголовок * по сравнению с * написанием только 'class X;' *. Первое влечет за собой как минимум один дополнительный доступ к диску. Есть основания строить фермы. –

1

Практика позволяет пользователю кода не думать о том, является ли класс регулярным или шаблонным. Пользователь просто # включает "соответствующее_fwd.h "и имеет ссылку на класс. Еще одно раздражение для пользователя - это хорошая вещь. Но если это небольшой проект или создатель класса - единственный пользователь класса, тогда это может быть более раздражающим. Поэтому это зависит.

+0

Хорошо, я вижу вашу мысль. Я все еще немного скептически отношусь к тому, что это стоит, учитывая дополнительные усилия. Кажется, что если бы я был просто пользователем, это было бы нормально, но если бы я тоже был дев, то время или энергия, которые я сохраняю, включая fwd.h, не задумываясь, компенсируется временем, потраченным на их создание ... – Geeho

Смежные вопросы