Сведения о вопросе

Getthesound

15:34, 19th August, 2020

Теги

Несколько классов в заголовочном файле по сравнению с одним заголовочным файлом для каждого класса

Просмотров: 510   Ответов: 13

По какой-либо причине наша компания имеет руководство по кодированию, которое гласит::

Each class shall have it's own header and implementation file.

Поэтому, если бы мы написали класс с именем MyString , нам понадобились бы ассоциированные MyStringh.h и MyString.cxx .

Кто - нибудь еще это делает? Кто-нибудь видел какие-либо последствия для производительности компиляции в результате этого? Действительно ли 5000 классов в 10000 файлов компилируются так же быстро, как 5000 классов в 2500 файлов? Если нет, то заметна ли разница?

[Мы кодируем C++ и используем GCC 3.4.4 как наш повседневный компилятор]



  Сведения об ответе

dump

23:46, 28th August, 2020

Термин здесь- единица перевода , и вы действительно хотите (если это возможно) иметь один класс на единицу перевода, т. е. одну реализацию класса на файл .cpp, с соответствующим файлом .h с тем же именем.

Обычно это более эффективно (с точки зрения compile/link)), чтобы делать вещи таким образом, особенно если вы делаете такие вещи, как инкрементная ссылка и так далее. Идея заключается в том, что единицы перевода изолированы таким образом, что, когда одна единица перевода изменяется, вам не нужно перестраивать много вещей, как это было бы, если бы вы начали собирать множество абстракций в одну единицу перевода.

Кроме того, вы обнаружите, что многие ошибки/диагностики сообщаются через имя файла ("ошибка в Myclass.cpp, строка 22"), и это помогает, если есть соответствие one-to-one между файлами и классами. (Или, я полагаю, вы могли бы назвать это перепиской 2 к 1).


  Сведения об ответе

LIZA

09:19, 27th August, 2020

Переполненный тысячами строк кода?

Наличие одного набора заголовочных / исходных файлов для каждого класса в каталоге может показаться излишним. А если количество классов приближается к 100 или 1000, то это может даже пугать.

Но, поиграв с источниками, следуя философии "давайте соберем все вместе", можно сделать вывод, что только тот, кто написал файл, имеет хоть какую-то надежду не потеряться внутри. Даже с IDE легко пропустить что-то, потому что, когда вы играете с источником 20 000 строк, вы просто закрываете свой ум для всего, что не совсем относится к вашей проблеме.

Реальный пример: иерархия классов, определенная в этих тысячах строк источников, замкнулась в алмазное наследование, и некоторые методы были переопределены в дочерних классах методами с точно таким же кодом. Это было легко упустить из виду (кто хочет исследовать/проверить исходный код в 20 000 строк?), и когда первоначальный метод был изменен (исправление ошибок), эффект не был столь универсальным, как исключено.

Зависимость становится круговой?

У меня была эта проблема с шаблонным кодом, но я видел аналогичные проблемы с обычным кодом C++ и C.

Разбивка источников на 1 заголовок для каждой структуры / класса позволяет вам:

  • Ускорьте компиляцию, так как вы можете использовать прямое объявление символов вместо включения целых объектов
  • Имеют циклические зависимости между классами ( § ) (т. е. класс A имеет указатель на B, А B имеет указатель на A)

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

Наличие отдельных заголовков делает код более модульным, быстрее компилируется и облегчает изучение его эволюции с помощью различных версий diffs

Для моей шаблонной программы мне пришлось разделить заголовки на два файла: файл .HPP, содержащий класс шаблона declaration/definition, и файл .INL, содержащий определения указанных методов класса.

Поместить весь этот код в один и только один уникальный заголовок означало бы поместить определения классов в начале этого файла, а определения методов-в конце.

И тогда, если кому-то нужна была только небольшая часть кода, с решением one-header-only, им все равно пришлось бы платить за более медленную компиляцию.


  Сведения об ответе

Chhiki

15:31, 13th August, 2020

Мы делаем это на работе, просто легче найти материал, если класс и файлы имеют одно и то же имя. Что касается производительности, то вы действительно не должны иметь 5000 классов в одном проекте. Если вы это сделаете, то, возможно, потребуется провести некоторый рефакторинг.

Тем не менее, есть случаи, когда у нас есть несколько классов в одном файле. И это тогда, когда это просто частный вспомогательный класс для основного класса файла.


  Сведения об ответе

P_S_S

08:22, 16th August, 2020

Помимо того, что это просто "clearer", разделение классов на отдельные файлы позволяет нескольким разработчикам не наступать друг другу на пятки. Когда придет время вносить изменения в ваш инструмент управления версиями, слияния будет меньше.


  Сведения об ответе

ASER

22:40, 25th August, 2020

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


  Сведения об ответе

PIRLO

16:31, 1st August, 2020

Большинство мест, где я работал, следовали этой практике. На самом деле я написал стандарты кодирования для BAE (Aust.) вместе с причинами, почему вместо того, чтобы просто вырезать что-то в камне без реального оправдания.

Что касается вашего вопроса об исходных файлах, то это не столько время для компиляции, сколько вопрос о том, чтобы найти соответствующий фрагмент кода в первую очередь. Не все используют IDE. И знание того, что вы просто ищете MyClass.h и MyClass.cpp, действительно экономит время по сравнению с запуском "grep MyClass *.(h|cpp)" над кучей файлов и последующей фильтрацией операторов #include MyClass.h...

Имейте в виду, что существуют обходные пути для воздействия большого количества исходных файлов на время компиляции. Познакомиться с масштабными C дизайн программного обеспечения++ Джон Лакос за интересную дискуссию.

Вы также можете прочитать Совершенный код Стив McConnell за отличную главу, посвященную принципам кодирования. На самом деле, эта книга-отличное чтение, к которому я регулярно возвращаюсь


  Сведения об ответе

VERSUION

20:13, 21st August, 2020

Это обычная практика, особенно для того, чтобы иметь возможность включать .h в файлы, которые в этом нуждаются. Конечно, это влияет на производительность, но постарайтесь не думать об этой проблеме, пока она не возникнет :).
Лучше начать с разделенных файлов, а затем попытаться объединить .h, которые обычно используются вместе, чтобы улучшить производительность, если вам действительно нужно. Все это сводится к зависимостям между файлами, и это очень специфично для каждого проекта.


  Сведения об ответе

прога

18:47, 17th August, 2020

Наилучшая практика, как уже говорили другие, заключается в том, чтобы поместить каждый класс в свою собственную единицу перевода с точки зрения обслуживания кода и его понятности. Однако в крупномасштабных системах это иногда не рекомендуется - см. раздел под названием "Make Those Source Files Bigger" в этой статье Брюса Доусона для обсуждения компромиссов.


  Сведения об ответе

ASSembler

20:10, 29th August, 2020

Я нашел эти рекомендации особенно полезными, когда речь заходит о заголовочных файлах : http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Header_Files


  Сведения об ответе

SEEYOU

21:36, 8th August, 2020

Очень полезно иметь только один класс на файл, но если вы делаете свою сборку с помощью файлов bulkbuild, которые включают все отдельные файлы C++, это делает более быстрые компиляции, так как время запуска относительно велико для многих компиляторов.


  Сведения об ответе

lats

23:33, 21st August, 2020

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

Я лично группирую связанные классы в один файл, а затем даю такому файлу осмысленное имя, которое не нужно будет менять, даже если имя класса изменится. Наличие меньшего количества файлов также облегчает прокрутку дерева файлов. Я использую Visual Studio на Windows и Eclipse CDT на Linux, и у обоих есть сочетания клавиш, которые ведут прямо к объявлению класса, поэтому найти объявление класса легко и быстро.

Сказав это, я думаю, что как только проект завершен, или его структура имеет 'solidified', и изменения имен становятся редкими, может быть, имеет смысл иметь один класс на файл. Я бы хотел, чтобы был инструмент, который мог бы извлекать классы и помещать их в различные файлы .h и .cpp. Но я не вижу в этом ничего существенного.

Выбор также зависит от типа проекта, над которым вы работаете. На мой взгляд, этот вопрос не заслуживает черно-белого ответа, поскольку у любого выбора есть свои плюсы и минусы.


  Сведения об ответе

PAGE

18:41, 24th August, 2020

То же самое правило применяется и здесь, но оно отмечает несколько исключений, когда это разрешено подобным образом:

  • Деревья наследования
  • Классы, которые используются только в очень ограниченной области
  • Некоторые утилиты просто помещаются в общую 'utils.h'


  Сведения об ответе

9090

03:48, 11th August, 2020

Два слова: Окхэм Razor. Храните по одному классу на файл с соответствующим заголовком в отдельном файле. Если вы делаете иначе, например сохраняете часть функциональности в файле, то вы должны создать все виды правил о том, что составляет часть функциональности. Есть гораздо больше возможностей получить, сохраняя один класс на файл. И даже половина приличных инструментов может обрабатывать большое количество файлов. Будь проще, мой друг.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться