2011-06-21 6 views
21
  • Есть ли какой-либо предпочтительный способ организации, включающий директивы?
  • Лучше ли включить файлы, которые вам нужны, в файл .cpp вместо файла .h? Как-то повлияли единицы перевода?
  • Как насчет того, если мне это нужно как в файле .h, так и в файле .cpp, следует ли просто включить его в файл .h? Это будет иметь значение?
  • Является ли хорошей практикой хранить уже определенные файлы в предварительно скомпилированном заголовке (stdafx.h), например, std и сторонние библиотеки? Как насчет моих собственных файлов, следует ли включать их в файл stdafx.h по пути, когда я их создаю?

// myClass.h 
#include <string> 
// ^-------- should I include it here? -------- 

class myClass{ 
    myClass(); 
    ~myClass(); 

    int calculation() 
}; 

// myClass.cpp 
#include "myClass.h" 
#include <string> 
// ^-------- or maybe here? -------- 

[..] 

int myClass::calculation(){ 
    std::string someString = "Hello World"; 
    return someString.length(); 
} 


// stdafx.h 
#include <string.h> 
// ^--------- or perhaps here, and then include stdafx.h everywhere? ------- 
+1

Dupe. Это было задано много раз, часто он просто не связывал правильный: http://stackoverflow.com/questions/2762568/cc-include-file-order-best-practices – AJG85

+0

@ AJG85 этот вопрос спрашивает, что * заказать * Включение должно быть включено. Я не прошу о заказе - я спрашиваю, где должны быть расположены объекты, в каком файле. – Default

ответ

25
  1. Вы должны иметь их в верхней части файла, все в одном месте. Это то, чего все ждут. Кроме того, полезно, чтобы они были сгруппированы, например. сначала все стандартные заголовки, затем сторонние заголовки (сгруппированные по библиотеке), а затем ваши собственные заголовки. Соблюдайте этот порядок во всем проекте. Это упрощает понимание зависимостей. Как отмечает @James Kanze, также полезно поместить заголовок, который сначала объявит содержимое. Таким образом, вы убедитесь, что он работает, если он включен первым (это означает, что он не зависит от того, включает ли он, что он не включает себя).
  2. Держите область как можно меньше, так что изменение заголовка влияет на наименьшее количество единиц перевода. Это означает, что по возможности включите его только в файл cpp. Как прокомментировал @Pedro d'Aquino, вы можете уменьшить количество включений в заголовке, используя по возможности прямые декларации (в основном, когда вы используете только ссылки или указатели на данный тип).
  3. Оба - явно лучше, чем неявное.
  4. После некоторого чтения, я считаю, что вы должны включать только заголовки в PCH, если вы уверены, что они больше не меняются. Это касается всех стандартных заголовков, а также (возможно) сторонних библиотек. Для ваших собственных библиотек вы являетесь судьей.
+0

так, включая их в файл '.cpp', в основном, чтобы не включать их во все файлы, содержащие файл' .h'? – Default

+1

@Default: Да. Это минимизирует зависимости во всем вашем проекте, что хорошо по многим причинам. –

+3

+1 Все очень хороший совет. Мое правило состояло в том, чтобы включить минимальное количество заголовков в любой файл (будь то .cpp или .h), чтобы его компилировать, что означает, что большинство из них включает в .cpp, остальные в его .h. – vhallac

7

Эта статья о Header file include patterns должна быть вам полезна.

  • Есть ли предпочтительный способ организовать из них включает в себя директиву?

Да, вы можете найти их в указанной выше статье.

  • Что лучше включать файлы, необходимые в .cpp файл вместо заголовочного файла? Являются ли единицы перевода так или иначе затронуты?

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

  • Как насчет, если мне нужно это как в .h файл и CPP-файл, я должен просто включить его в .h файле? Будет ли это вопрос?

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

  • Это хорошая практика, чтобы сохранить уже определенные файлы в скомпилированных заголовка (stdafx.h), например, станд и сторонних библиотек? Как насчет моих собственных файлов, следует ли включать их в файл stdafx.h по пути, поскольку я создать их?

я лично не использовал скомпилированные заголовки, но там было обсуждение на них на Stackoverflow раньше:

Precompiled Headers? Do we really need them

5

Есть ли предпочтительный способ организовать из них включают в себя директивы?

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

Лучше ли включить файлы, которые вам нужны, в .cpp-файл вместо файла .h?

В общем, да. Это уменьшает количество раз, которое компилятор должен открыть и прочитать файл заголовка, чтобы увидеть там включенные охранники. Это может сократить общее время компиляции. Иногда рекомендуется пересылать-объявлять как можно больше классов в заголовках и фактически включать их только в .cpp, по той же причине. Например, люди «Qt» делают это.

Являются ли единицы перевода затронуты каким-то образом?

В смысловом смысле нет.

Как насчет того, если мне это нужно в файле .h и .cpp, следует ли просто включить его в файл .h? Это будет иметь значение?

Просто включите его в заголовок.

Полезно ли хранить уже определенные файлы в предварительно скомпилированном заголовке (stdafx.h), например, std и сторонние библиотеки? Как насчет моих собственных файлов, следует ли включать их в файл stdafx.h по мере их создания?

Предварительно скомпилированные заголовки могут значительно сократить время компиляции.Например: один из моих проектов, который включает в себя boost::spirit::qi, составляет 20 секунд с PCH, а 80 секунд - без. В общем, если вы используете какую-то сильно заполненную шаблонами библиотеку, такую ​​как boost, вы бы хотели использовать преимущество PCH.

Что касается вопроса в вашем примере кода:, так как вы не используете зЬй :: строку в заголовке, то лучше включить его в файл .cpp. Это нормально #include <string> в stdafx.h тоже - но это просто добавит немного сложности вашему проекту, и вы вряд ли заметите ускорение компиляции.

1

(4) Я бы не рекомендовал включать любые дополнительные файлы в stdafx.h. или подобных файлов "include_first.h". Прямое включение в файлы cpp или конкретные h позволяет явно выражать зависимости вашего кода и исключать избыточные зависимости. Особенно полезно, когда вы решили разложить монолитный код на несколько библиотек или dll. Лично я использую такие файлы, как «include_first.h» (stdafx.h) только для целей конфигурации (этот файл содержит только определения макросов для текущей конфигурации приложения).
Можно предоставить предварительно скомпилированные заголовки для ваших собственных файлов, пометив другой файл, чтобы остановить прекомпиляцию вместо stdafx.h (например, вы можете использовать специальный пустой файл с именем «stop_pch.h»).
Обратите внимание, скомпилированные заголовки могут не работать должным образом для некоторых видов замысловатого использования препроцессора (частичном, для некоторой техники, используемой в BOOST_PP_ *)

0

Это может быть важно заметить, что порядок классов в блоке перевода должны быть правильными или некоторые функции C++ просто отключены и приводят к ошибке времени компиляции.

Edit: Добавление примеров:

class A { }; 
class B { A a; }; // order of classes need to be correct 
1

С точки зрения производительности:

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

Кроме того, с помощью компилятора Microsoft вы можете поместить это в верхней части каждого файла заголовка:

#pragma once 

Это позволяет компилятору полностью пропустить этот файл после первого появления, сохранения операций ввода/вывода. Традиционный шаблон ifndef/define/endif требует открытия и разбора файла каждый раз, когда он включен, что, конечно, занимает некоторое время. Это, безусловно, может накапливаться и становиться заметным!

(Обязательно оставите традиционную охрану там, для переносимости.)

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