Общая информация

Каждый файл исходного кода (.cc) должен иметь ассоциированный с собой заголовок.

Для этого правила есть исключения, например, в случае с юнит-тестами или файлами с точкой входа в программу (функцией main).

Мы используем для включения только символы <, >. Кавычки не рекомендуются для использования, если в этом нет крайней необходимости.

#include <cat/meow.h> // 😊 правильно
#include "cat/meow.h" // 😡 неправильно

Расширения файлов

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

Header-guard

Каждый заголовочный файл должен иметь header-guard в виде директивы #pragma once.

Неправильный код
#ifndef MEOW_HEADER
#define MEOW_HEADER
 
/* ... */
 
#endif // MEOW_HEADER
Правильный код
#pragma once
 
/* ... */

Включение других заголовочных файлов

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

Примеры:

Неправильный код
#include <iostream>
 
std::string a = "qwe";
std::cout << a << std::endl;

Данный код может привести к ошибке компиляции на некоторых платформах.

Правильный код
#include <string>
#include <iostream>
 
std::string a = "qwe";
std::cout << a << std::endl;

Объявления наперед (forward-declarations)

Используйте объявления наперед там, где это возможно.

Предупреждение

Не стоит использовать объявления наперед в случае с шаблонными типами и символами из пространства имен std::.

В случае с заголовочными файлами из стандартной библиотеки поощряется использование стандартных заголовков для объявления наперед, если такие существуют. Например, вместо <iostream> включать <iosfwd> (cppreference).

Порядок включений

Рекомендуется использовать следующий порядок включений:

  • Заголовки языка C (<cstdlib>, <cstring>)
  • Заголовки стандартной библиотеки C++ (<iostream>, <string>)
  • Заголовки ОС (<unistd.h>, <windows.h>)
  • Заголовки системных библиотек (<python.h>, <curl.h>)
  • Заголовки сторонних библиотек (<gtest/gtest.h>, <leaf/utils/rtti.h>)
  • Заголовки Qt. Для заголовков Qt доступны 2 равнозначных стиля включения:
    • Включение по полному имени и модулю: <QtCore/QString>, <QtWidgets/QApplication
    • Включение по исходному заголовочному файлу: <qstring.h>, <qobject.h>
  • Публичные заголовки текущей библиотеки/проекта: <cats/meow.h>
  • Приватные заголовки текущей библиотеки/проекта: <meow_impl.h>
  • Условные включения (т.е. обернутые в #if/#endif)
Пример
#include <cstdlib>
#include <cstdbool>
#include <string>
#include <iostream>
#include <windows.h>
#include <python.h>
#include <gtest/gtest.h>
#include <leaf/leaf.h>
#include <leaf/utils/rtti.h>
#include <qcoreapplication.h>
#include <qobject.h>
#include <qqmlapplicationengine.h>
#include <this_project/cat/meow.h>
#include <this_project/dog/bark.h>
#include <cat/meow_p.h>
#include <dog/bark_p.h>
 
#if defined(CATS)
# include <this_project/cat/purr.h>
#endif

Замечание

Не допускается использование относительных путей в директиве #include.

Далее: Область видимости