Стандарт кодирования предписывает правила оформления кода на языке программирования C++. Все правила, применимые для языка программирования С, должны применяться в коде, написанном на этом языке.
Настоящий стандарт учитывает особенности некоторых вспомогательных инструментов разработчика, используемых в проекте. Примером такого инструмента может служить пакет doxygen.
Настоящий документ является скорее справочником, чем исчерпывающим объяснением выбранных решений.
Отступления от данного стандарта допускаются, если они облегчают чтение кода.
Стандарт не является панацеей от написания плохого кода.
Стандарт практически не описывает семантические аспекты использования языка. Дальнейшие редакции могут быть расширены этими элементами.
Файлы
Заголовочные файлы должны иметь расширение .h, файлы с исходным текстом на С++ .срр, файлы с исходным текстом на С .с.
В общем случае заголовочный файл должен содержать объявление одного класса. Возможно объявление нескольких вспомогательных классов, например, предикатов. Вспомогательные классы, как правило, элементарны и имеют гораздо меньший размер, чем основные.
Файл .cpp должен совпадать по имени с заголовочным файлом и содержать определение объявленных в .h классов.
Максимальная длина строки в файле - 80 символов. В случае переноса строки используйте вертикальное выравнивание со сдвигом.
Максимальный размер файла - 1000 строк
Старайтесь ограничивать размер функции 100 строками.
Правила именования файлов совпадают с правилами формирования идентификаторов
В исходных текстах запрещается использовать специальные символы TAB и page break. Символ TAB должен быть замещен на пробелы автоматически редактором текстов. (Исключение - Makefile, где символ TAB имеет специальное значение)
Каждый файл имеет комментарий, размещаемый в самом начале файла, за которым идет все остальное
Содержимое заголовочного файла должно размещаться внутри директив условной компиляции. Например, для файла MyClass.h:
#ifndef MYCLASS_H
#define MYCLASS_H
. . .
#endif
Все включаемые директивой #include файлы должны находиться в начале файла
Включаемые файлы должны быть отсортированы и сгруппированы. Сортировка производится от низкоуровневых к высокоуровневым файлам. Для группировки используется одна или несколько пустых строк. Например:
Для формирования идентификаторов используется английский язык с корректным написанием слов
Использование собственных аббревиатур в идентификаторах и сокращений сводится к минимуму. Использование общепринятых аббревиатур допускается, например: NMEA.
Каждое слово, входящее в состав идентификатора пишется с большой буквы. Слова пишутся слитно, например
HelloWorld
Для имен типов (классов, структур, перечислений) допускаются префиксы. Каждый из разработчиков может пользоваться своим собственным префиксом, например:
SMyOwnClass
Использование символа '_' в идентификаторах недопустимо
Использование зарезервированных различными международными стандартами идентификаторов не допускается
bool переменные, как правило, должны именоваться с префиксом Is или Has, например:
bool IsDoorClosed;
Имена файлов, как правило, совпадают с именами классов, содержащихся в них.
При именовании классов и их методов старайтесь выбирать имена таким образом, чтобы вызов вида
MyObject.Method()
Читался как имеющая смысл фраза.
Избегайте именования локальных объектов таким образом, что они перекрывают внешние имена
Если имя формального аргумента метода класса конфликтует с именем члена класса, допускается использование идентификатора формального аргумента с маленькой буквы, например:
Избегайте имен, незначительно отличающихся друг от друга и имен, использующих похожие символы, такие как '0', '1' и 'O', 'l'.
В качестве счетчиков циклов допускаются локальные однобуквенные переменные. Предпочитайте именовать их в такой последовательности: k, j, m, n, i.
Если макросы все-таки используются, то давайте им имена, использующие только заглавные буквы и символы подчеркивания в качестве разделителей.
Расположение текста
Пишите код "чанками", разделенными пустыми строками
Для форматирования текста используются отступы, равные 4 пробелам
Используйте вертикальное выравнивание
Блоки объявления переменных должны быть выровнены
int SomeIntegerValue; //!< Remark1unsignedlong SomeLongValue; //!< Remark2bool SomeBooleanValue; //!< Remark3
Стартовая позиция типа данных, имени переменной и комментария должны попадать на позицию табулятора. После типа должно быть не менее 2 пробелов. Символы * и & относятся к типу, а не к имени. Комментарий отделяется не менее чем 2 пробелами от объявления переменной.
Фигурные скобки должны быть выровнены с использованием стиля Олмэна:
void DoSomething ( void )
{
if ( x != y )
{
y = x;
}
else
{
; // Do nothing
}
}
Каждая фигурная скобка занимает отдельную строку. Исключение: определение пустых подставляемых методов в заголовочных файлах.
Операторы while, for и if всегда используют блоки в фигурных скобках, даже если синтаксической необходимости нет
Элементы оператора switch должны быть выровнены в соответствии с позициями отступа. Альтернатива default должна присутствовать всегда. Каждая из альтернатив должна иметь break
Перенос длинных строк должен осуществляться после , ; и других операторов.
Операторы сравнения должны быть окружены пробелами
if ( a <= b )
Вслед за ключевыми словами должен идти пробел
for ( ; ; )
Вслед за , ; должен идти пробел. Перед этими символами пробела быть не должно.
Перед символами ( [ < не должно быть пробела. После них должен быть пробел.
Вокруг : ) ] > = должны быть пробелы. Исключение составляет вызов функции без аргументов. В этом случае допускается писать круглые скобки без пробелов (MyVector.end()).
Вокруг операторов . и -> пробелов быть не должно.
После операции разыменования (*) и взятия адреса (&) пробела быть не должно.
После знаков унарных операций не должно быть пробелов
Операторы инкрементации и декрементации должны писаться слитно с объектом, к которому они применяются
Символы математических операций должны быть окружены пробелами
Ключевое слово template со списком параметров должно располагаться на отдельной строке
template < class EventType, class StateType >
class SStateMachine
{
. . .
};
В прототипах все аргументы должны быть именованы. После имени типа должно быть не менее 2 пробелов. В случае переноса списка на следующую строку необходимо пользоваться вертикальным выравниваем.
Комментарии
Комментарии учитывают использование системы генерации документации по исходному тексту doxygen. Для маркировки комментариев используется комбинация символов //!, /*! . . . */ и //!<. Последний означает, что комментарий относится к предшествующему элементу. Кроме того, используются комбинации @param для описания параметров функций и методов и @return для описания возвращаемых значений.
Комментарии даются на корректном английском языке
Размер комментария пропорционален сложности комментируемого объекта
Предпочтительный формат комментария в стиле C++: //
Многострочные комментарии должны быть выровнены
// First line// Second line// Third line
или
/* Short line *//* Extended size line *//* Very very very very long line */
В случае многострочного комментария в стиле C его предпочтительный вид такой:
/*
* Some remarks
* More remarks
*/
Комментарии, предшествующие комментируемому элементу, располагаются с отступом 4 пробела
//! This is the remarkbool SomeBooleanValue;
//! This is the first line//! More detailed descriptionbool SomeBooleanValue;
Комментарии могут даваться разными способами: предшествующие комментируемому элементу, находящиеся в той же строке, что и комментируемый элемент. Комментарий, находящийся в той же строке должен быть отделен не менее чем двумя пробелами от комментируемого элемента.
//! This is the first type of the remarkbool SomeBooleanValue;
bool SomeBooleanValue; //!< Many lines remark//!< Second line of the remark
Каждая переменная должна быть прокомментирована
Каждый тип данных пользователя (класс, структура, объединение и т.п.) должен быть снабжен комментарием
//! The SMyOwnClass is created for the special purpose//! And should be used everywhere it is possible//! With no obligation to send a post cardclass SMyOwnClass
{
. . .
};
Каждая функция (метод класса) должна быть снабжена комментарием
//! The function transforms string representation into integer//! @param InputValue is a stringed value//! @param Base is a scale of notation//! @return transformed value of the given scale of notationlong SuperFunction ( const string & InputValue, long Base );
Каждое пространство имен должно быть снабжено комментарием
В начале каждого исходного файла проекта должен быть комментарий вида:
//// File: Template.h//// Creation date: July 27th 2003//// Author: Sergey Satskiy//// Purpose: Template for all the headers//// Copyright (c) 2005 Sergey Satskiy//// $//
каждая строка начинается с нулевой колонки.
В случае, если doxygen не распознает многострочный предшествующий комментарий в стиле C++, используйте следующую форму записи:
/*! The function transforms string representation into integer
* @param InputValue is a stringed value
* @param Base is a scale of notation
* @return transformed value of the given scale of notation
*/long SuperFunction ( const string & InputValue, long Base );
Допускается использовать и другие, не показанные выше, специальные идентификаторы системы doxygen.
Дополнительные комментарии, данные автором помимо перечисленных выше обязательных, приветствуются.
Использование языка
Вместо NULL используйте 0
Модификатор const должен использоваться везде, где это применимо
Вместо определения замещений констант директивой #define используйте const.
В объявлении класса секции должны следовать в следующем порядке: public, protected, private. В определении класса должен использоваться тот же порядок.
Не используйте оператор goto
Избегайте глубокой вложенности операторов, блоков и структур. Предпочитайте способ обработки с простой проверкой и выходом "на бок".
В одном операторе объявляется одна переменная
Избегайте использования оператора ?
Избегайте использования макросов
Вложенные if else операторы должны быть выровнены так, как если бы они были самостоятельными операторами.
Инициализируйте переменные в момент объявления везде, где это возможно.
Конструкторы должны инициализировать по возможности все члены - данные. Инициализация должна даваться, по возможности, в списке инициализации. Помните о порядке инициализации.
Не забывайте делать деструкторы базовых классов виртуальными
Используйте контейнеры и алгоритмы STL
Предпочитайте явно указывать в коде вызов конструктора при инициализации значений переменных
int Salary( 0 ); // Not int Salary = 0;for ( vector<int>::iterator k( MyVector.begin() ); k != MyVector.end(); ++k )
Оператор присваивания должен быть один в строке. Множественные присваивания не допускаются.
Не используйте сравнения в математических выражениях
Не boolean результаты выражений должны использовать оператор сравнения. Не используйте неявный != 0.
if ( ObjectPointer != 0 ) // OKif ( ObjectPointer ) // Not allowed
Избегайте присваиваний в операторах сравнения
Избегайте использования оператора , (запятая)
Используйте операторы приведения в стиле C++, а не преобразования по умолчанию или преобразования в стиле С
Используйте for ( ; ; ) для записи бесконечного цикла
Для обработки ошибок пользуйтесь исключениями
Используйте sizeof а не константы
Помните о методах классов, генерируемых компилятором по умолчанию
Установите максимальный уровень выдачи предупреждений компилятором. Добивайтесь компиляции без единого предупреждения.
Избегайте перегрузки по numerical и pointer типам. Это влечет неоднозначности.
Используйте встроенный тип bool
По возможности не используйте RTTI
Предпочитайте ссылки указателям
Предпочитайте long типу int
Предпочитайте double типу float
Предпочитайте префиксную форму операторов ++ и -- везде, где это возможно
Пространства имен
Пространства имен должны использоваться везде, где это применимо
Библиотечный код должен быть помещен в пространство имен
Библиотечный код не должен использовать директиву using namespace для нужных ему определений. Вместо этого должен быть использован оператор разрешения области видимости.