Организация заголовочных файлов класса C++

Страница инструмента ngen пролила бобы (или, по крайней мере, обеспечила хорошее сравнение собственных изображений и JIT-скомпилированных изображений). Исполняемые файлы, которые скомпилированы досрочно, обычно имеют следующие преимущества:

  1. Нативные изображения загружаются быстрее, потому что они не имеют большого количества операций запуска и требуют статического количества меньше памяти (память требуемый компилятором JIT);
  2. Собственные изображения могут совместно использовать библиотечный код, в то время как JIT-скомпилированные изображения не могут.

Скомпилированные исполняемые файлы «точно в срок» обычно имеют верхний в следующих случаях:

  1. Нативные изображения больше, чем их байт-код,
  2. Родные изображения должны быть регенерированы всякий раз, когда изменяется исходная сборка или одна из ее зависимостей.

Необходимость регенерации изображения, которое выполняется заранее, каждый раз, когда один из его компонентов является огромным недостатком для собственных изображений. С другой стороны, тот факт, что JIT-скомпилированные изображения не могут совместно использовать библиотечный код, может привести к серьезному поражению памяти. Операционная система может загружать любую родную библиотеку в одном физическом местоположении и делиться неизменяемыми ее частями с каждым процессом, который хочет ее использовать, что приводит к значительной экономии памяти, особенно с системными рамками, которые практически каждая программа использует. (Я полагаю, что это несколько компенсируется тем фактом, что JIT-скомпилированные программы только компилируют то, что они на самом деле используют.)

Общее мнение Microsoft по этому вопросу заключается в том, что крупные приложения обычно выигрывают от компиляции вперёд - времени, в то время как малые вообще не делают.

50
задан Don Kirkby 8 December 2008 в 20:10
поделиться

5 ответов

Некоторые общие руководящие принципы:

  • Разделяют на пары Ваши интерфейсы с реализациями. Если Вы имеете foo.cxx, все определенное там должно быть объявлено в foo.h.
  • Гарантируют что каждый заголовочный файл #includes все другие необходимые заголовки или предописания, необходимые для независимой компиляции.
  • Сопротивляются искушению создать "все" заголовок. Они всегда - проблема в будущем.
  • Помещенный ряд связанного (и взаимозависимый) функциональность в единственный файл. Java и другие среды поощряют one-class-per-file. С C++ Вы часто хотите один набор [1 117] классы на файл. Это зависит от структуры Вашего кода.
  • Предпочитают предописание [более чем 112] с, когда это возможно. Это позволяет Вам повреждать циклические зависимости от заголовка. По существу, для циклических зависимостей через отдельные файлы, Вы хотите граф зависимостей файла, который выглядит примерно так:
    • A.cxx требует A.h, и B.h
    • B.cxx требует A.h, и B.h
    • A.h требует B.h
    • B.h, независимо (и вперед - объявляет классы, определенные в [1 112])

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

  • При необходимости, используйте понятие "частных заголовков". Таким образом, заголовочные файлы, которые требуются несколькими исходными файлами, но никогда не требуются открытым интерфейсом. Это могло быть файлом с общими подставляемыми функциями, макросами или внутренними константами.
  • Разделяют Ваш открытый интерфейс от Вашей частной реализации на уровне файловой системы. Я склонен использовать include/ и src/ подкаталоги в моем C или проектах C++, где include/ имеет все мои общедоступные заголовки, и src/ имеет все мои источники. и частные заголовки.

я рекомендовал бы найти копию книги John Lakos Крупномасштабной Разработкой программного обеспечения C++ . Это - довольно значительная книга, но если Вы просто будете скользить посредством некоторых его обсуждений физической архитектуры, Вы изучите много.

66
ответ дан Tom 7 November 2019 в 20:55
поделиться

Проверьте C и стандарты кодирования C++ в НАСА Центр космических полетов имени Годдарда . Одно правило, что я особенно отметил в стандарте C и принял в своем собственном коде, является тем, которое осуществляет 'автономную' природу заголовочных файлов. В файле реализации xxx.cpp для заголовка xxx.h, удостоверьтесь, что xxx.h является первым включенным заголовком. Если заголовок не будет автономным никогда, то компиляция перестанет работать. Это - красиво простое и эффективное правило.

единственное время это приводит Вас к сбою, то, если Вы портируете между машинами, и xxx.h заголовок включает, скажем, <pqr.h>, но <pqr.h> требует средств, которые, оказывается, сделаны доступными заголовком <abc.h> на исходной платформе (таким образом <pqr.h> включает <abc.h>), но средства не сделаны доступными <abc.h> на другой платформе (они находятся в def.h вместо этого, но <pqr.h> не включает <def.h>). Это не отказ правила, и проблема более легко диагностирована и решена, если Вы следуете правилу.

8
ответ дан Jonathan Leffler 7 November 2019 в 20:55
поделиться

Проверьте раздел заголовочного файла в руководство по стилю Google

6
ответ дан tresf 7 November 2019 в 20:55
поделиться

Еще одна точка в дополнение к другим здесь:

не включают частных определений во включать файл. Например, любое определение, которое используется только в xxx.cpp, должно быть в xxx.cpp, не xxx.h.

Кажется очевидным, но я часто вижу его.

3
ответ дан Steve Fallows 7 November 2019 в 20:55
поделиться

ответ Tom является превосходным!

Только вещь, которую я добавил бы, никогда не состоит в том, чтобы иметь "объявлений использования" в заголовочных файлах. Им нужно только позволить в файлах реализации, например, foo.cpp.

логика для этого хорошо описана в превосходной книге "Ускоренный C++" (, ссылка Amazon - санированный для деточки сценария связывает нацистов)

5
ответ дан Community 7 November 2019 в 20:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: