Какой порядок должен включать файлы быть указанным, т.е. каковы причины включения одного заголовка перед другим?
Например, системные файлы, STL и Повышение идут, прежде или после того, как локальные включают файлы?
Я не думаю, что есть рекомендуемый порядок, если он компилируется! Что раздражает, так это то, что некоторые заголовки требуют, чтобы сначала были включены другие заголовки ...Это проблема самих заголовков, а не порядка включения.
Лично я предпочитаю перейти от локального к глобальному, каждый подраздел в алфавитном порядке, то есть:
Мое обоснование для 1. состоит в том, что он должен доказать, что каждый заголовок (для которого есть cpp) может быть #include
d без предварительных условий. А остальное, кажется, логически вытекает отсюда.
Это не субъективно. Убедитесь, что ваши заголовки не полагаются на #include
d в определенном порядке. Вы можете быть уверены, что не имеет значения, в каком порядке вы включаете заголовки STL или Boost.
Сначала включите заголовок, соответствующий .cpp ... другими словами, source1.cpp
должен включать source1. h
перед включением чего-либо еще. Единственное исключение, о котором я могу думать, - это использование MSVC с предварительно скомпилированными заголовками, и в этом случае вы вынуждены включать stdafx.h
прежде всего.
Обоснование: Включение source1.h
перед любыми другими файлами гарантирует, что он может работать автономно без зависимостей. Если source1.h
принимает зависимость от более поздней даты, компилятор немедленно предупредит вас, чтобы вы добавили необходимые форвардные объявления в source1.h
. Это, в свою очередь, гарантирует, что заголовки могут быть включены в любом порядке их иждивенцами.
Пример:
source1.h
class Class1 {
Class2 c2; // a dependency which has not been forward declared
};
source1.cpp
#include "source1.h" // now compiler will alert you saying that Class2 is undefined
// so you can forward declare Class2 within source1.h
...
Пользователи MSVC: Я настоятельно рекомендую использовать предварительно скомпилированные заголовки. Итак, переместите все директивы #include
для стандартных заголовков (и других заголовков, которые никогда не изменятся) в stdafx.h
.
Чтобы добавить свой кирпич к стене.
Обычно я говорю так:
// myproject/src/example.cpp
#include "myproject/example.h"
#include <algorithm>
#include <set>
#include <vector>
#include <3rdparty/foo.h>
#include <3rdparty/bar.h>
#include "myproject/another.h"
#include "myproject/specific/bla.h"
#include "detail/impl.h"
Каждая группа отделяется пустой строкой от следующей:
Также обратите внимание, что, помимо системных заголовков, каждый файл находится в папке с именем своего пространства имен просто потому, что их легче отслеживать вниз по этой дороге.
Включайте от наиболее специфичного к наименее специфичному, начиная с соответствующего .hpp для .cpp, если такой существует. Таким образом, будут выявлены любые скрытые зависимости в заголовочных файлах, которые не являются самодостаточными.
Это осложняется использованием предварительно скомпилированных заголовков. Один из способов обойти это, не делая свой проект специфичным для компилятора, - использовать один из заголовков проекта в качестве включаемого файла предварительно скомпилированного заголовка.
Я уверен, что это не является рекомендуемой практикой в здравом мире, но мне нравится выстраивать системные include по длине имени файла, сортируя их лексически в пределах одной длины. Например:
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
Я думаю, что это хорошая идея - включать свои собственные заголовки перед чужими, чтобы избежать позора зависимости порядка включения.
Я следую двум простым правилам, которые избегают подавляющего большинства проблем:
Я также следую рекомендациям:
Другими словами:
#include <stdio.h>
#include <string.h>
#include "btree.h"
#include "collect_hash.h"
#include "collect_arraylist.h"
#include "globals.h"
Хотя, будучи руководящими принципами, это субъективная вещь. Правила, с другой стороны, я применяю жестко, вплоть до предоставления «оберточных» заголовочных файлов с включенными защитами и сгруппированных включений, если какой-то неприятный сторонний разработчик не подписывается под моим видением :-)
Я рекомендую:
И, конечно же, алфавитный порядок внутри каждого раздела, где это возможно.
Всегда используйте объявления пересылки, чтобы избежать ненужных #include
в заголовочных файлах.