Что должно войти в.h файл?

При делении кода на несколько файлов, что точно должно войти в.h файл и что должно войти в .cpp файл?

89
задан Mgetz 9 December 2014 в 14:26
поделиться

12 ответов

заголовочные файлы (. h)) предназначены для предоставления информации, которая будет необходима в нескольких файлах. Такие вещи, как объявления классов, прототипы функций и перечисления обычно идут в заголовочных файлах. Одним словом, "определения".

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

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

.
104
ответ дан 24 November 2019 в 07:16
поделиться

То, что компилирует в ничто (нулевой двоичный отпечаток), попадает в заголовочный файл.

Переменные не компилируются в ничто, а с помощью объявлений типов (поскольку они описывают только поведение переменных).

функции не компилируют, а встроенные функции компилируют (или макросы), потому что они создают код только там, где вызываются.

шаблоны - это не код, это только рецепт создания кода. так что они также попадают в h-файлы.

.
6
ответ дан 24 November 2019 в 07:16
поделиться

в дополнение ко всем остальным ответам, я скажу вам, что вы НЕ должны помещать в заголовочный файл:
с помощью декларации (наиболее распространенной является с использованием пространства имён std;) не должны появляться в заголовочном файле, так как они загрязняют пространство имён исходного файла, в который он включен.

.
16
ответ дан 24 November 2019 в 07:16
поделиться

Ваши объявления классов и функций плюс документация и определения для встроенных функций/методов (хотя некоторые предпочитают помещать их в отдельные .inl-файлы).

.
1
ответ дан 24 November 2019 в 07:16
поделиться

В общем, вы помещаете объявления в заголовочный файл и определения в имплементационный (.cpp) файл. Исключением являются шаблоны, где определение также должно идти в заголовке.

Этот вопрос и подобные ему часто задавали на SO - см. Почему заголовочные файлы и .cpp файлы находятся в C++? и C++ заголовочные файлы, например, разделение кода.

.
3
ответ дан 24 November 2019 в 07:16
поделиться

В основном заголовочный файл содержит скелет класса или декларацию (часто не меняется)

, а cpp-файл содержит реализацию класса (часто меняется).

1
ответ дан 24 November 2019 в 07:16
поделиться

заголовочный файл (.h) должен быть для деклараций классов, структур и их методов, прототипов и др. Реализация этих объектов производится в cpp.

in . h

    class Foo {
    int j;

    Foo();
    Foo(int)
    void DoSomething();
}
0
ответ дан 24 November 2019 в 07:16
поделиться

Я бы ожидал увидеть:

  • объявления
  • комментарии
  • определения, помеченные inline
  • шаблоны

, хотя на самом деле ответ - это то, что не следует вводить:

  • определений (может привести к тому, что вещи будут умножаться)
  • с помощью деклараций/директив (заставляет их использовать любого, включая ваш заголовок, может привести к появлению знаков заголовка)
0
ответ дан 24 November 2019 в 07:16
поделиться

The header Defines something but doesn't tell anything about the implementation. ( Исключая шаблоны в этом "метафоре".

При этом нужно разделить "определения" на подгруппы, в данном случае есть два типа определений.

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

Теперь, конечно, я говорю о первой подгруппе.

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

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

0
ответ дан 24 November 2019 в 07:16
поделиться
  • Заголовочные файлы - не стоит слишком часто менять при разработке -> надо думать и писать их сразу (в идеальном случае)
  • Исходные файлы - изменения при реализации
0
ответ дан 24 November 2019 в 07:16
поделиться

Заголовок (.h)

  • Макросы и включает в себя необходимые для интерфейсов (как можно меньше)
  • Объявление функций и классов
  • Документация по интерфейсу
  • Объявление встроенных функций/методов, если таковые имеются
  • экстернов к глобальным переменным (если таковые имеются)

Тело (. cpp)

  • Rest of macros and includes
  • Include the header of the module
  • Definition of functions and methods
  • Global variables (if any)

Rest of macros and includes

  • Include the header of the module
  • Definition of functions and methods
  • Global variables (if any)
  • As a rule of thumb, you put the "shared" part on the .h (the part that other modules must be able to see) and the "not shared" part on the .cpp

    PD: Yes, I've included global variables. Я использовал их несколько раз, и важно не определять их в заголовках, иначе вы получите множество модулей, каждый из которых определяет свою собственную переменную.

    EDIT: Модифицировано после комментария David

    .
    0
    ответ дан 24 November 2019 в 07:16
    поделиться

    Дело в том, что на Си++ это несколько сложнее, чем организация заголовков/исходников на Си.

    Что видит компилятор?

    Компилятор видит один большой исходный (.cpp) файл с правильно включенными заголовками. Исходный файл - это единица компиляции, которая будет скомпилирована в объектный файл.

    Так зачем нужны заголовки?

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

    В этом случае существует два экземпляра одной и той же информации. Что является злом...

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

    Переместите в заголовок объявления о том, что нужно совместно использовать между несколькими источниками

    Ничего больше?

    В C++ есть некоторые другие вещи, которые можно поместить в заголовок, потому что они тоже должны быть общими:

    • inline code
    • templates
    • constants (обычно те, которые вы хотите использовать внутри коммутаторов). ...)

    Переместите в заголовок ВСЕ, что должно быть общим, включая общие реализации

    Значит ли это, что внутри заголовков могут быть исходники?

    Да. На самом деле, есть много разных вещей, которые могут быть внутри "заголовка" (i. e. shared between sources).

    • Forward declarations
    • declarations/definition of functions/structs/classes/templates
    • implementation of inline and templated code

    It becomes complicated, and in some cases (круговые зависимости между символами), impossible to keep it in one header. Заголовки можно разбить на три части

    Это означает, что в крайнем случае можно иметь:

    • заголовок прямой декларации
    • заголовок декларации/определения
    • заголовок реализации
    • источник реализации

    Представьте себе, что у нас есть шаблонированный MyObject. Мы могли бы иметь:

    // - - - - MyObject_forward.hpp - - - - 
    // This header is included by the code which need to know MyObject
    // does exist, but nothing more.
    template<typename T>
    class MyObject ;
    

    .

    // - - - - MyObject_declaration.hpp - - - - 
    // This header is included by the code which need to know how
    // MyObject is defined, but nothing more.
    #include <MyObject_forward.hpp>
    
    template<typename T>
    class MyObject
    {
       public :
          MyObject() ;
       // Etc.
    } ;
    
    void doSomething() ;
    

    .

    // - - - - MyObject_implementation.hpp - - - - 
    // This header is included by the code which need to see
    // the implementation of the methods/functions of MyObject,
    // but nothing more.
    #include <MyObject_declaration.hpp>
    
    template<typename T>
    MyObject<T>::MyObject()
    {
       doSomething() ;
    }
    
    // etc.
    

    .

    // - - - - MyObject_source.cpp - - - - 
    // This source will have implementation that does not need to
    // be shared, which, for templated code, usually means nothing...
    #include <MyObject_implementation.hpp>
    
    void doSomething()
    {
       // etc.
    } ;
    
    // etc.
    

    Вау!

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

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

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

    Заключение

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

    Но в тот день, когда у вас появятся круговые зависимости между шаблонированными объектами, не удивляйтесь, если ваша организация кода станет несколько более "интересной", чем обычная организация заголовков/кодов...

    ^_^

    .
    51
    ответ дан 24 November 2019 в 07:16
    поделиться
    Другие вопросы по тегам:

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