не уверен, что мой вопрос соответствует всем правилам для вопроса StackOverflow, но я думаю, что это будет полезно для будущих пользователей.C++ стиль кодирования
Теперь мне нужно выбрать стиль кодирования для нескольких проектов на C++, где я участвую. Эти проекты достаточно велики, и на каждом из них будет работать несколько программистов. Поэтому нам нужно уравнять наш стиль кода. Также мы хотим выбрать стиль кодирования, который является социально приемлемым, поэтому сначала я расскажу, что мы уже решили. Мой вопрос: если некоторые из наших выборов не являются социально непринятыми, а также то, что другие обычно используют правила стиля кодирования на C++.
Так вот, что мы выбрали:
именования файлов
начинаться с заглавной буквы и имеют прописную букву для каждого слова (нет подчеркивания, без пробелов).
Например:
VeryImportantClass.h
VeryImportantClass.cpp
пространство имен именования
начинаться с заглавной буквы и имеют прописную букву для каждого слова (нет подчеркивания, без пробелов). Также должно быть уместно выравнивание.
Например:
namespace Drinks
{
namespace AlcoholDrinks
{
}
}
пространство имен Структура
В файле заголовка имеют только функции/методы прототипов, реализация в файле cpp
, избегать использования using namespace
для файла реализации.
Пример:
//header
namespace CommonStuff
{
namespace SystemParameters
{
bool IfWindows();
//some more stuff...
}
}
//cpp file
namespace CommonStuff
{
namespace SystemParameters
{
bool IfWindows()
{
//some stuff...
return ...;
}
}
}
Классы и структуры именования
начинаться с заглавной буквы и имеют прописную букву для каждого слова (нет подчеркивания, без пробелов). Нет C как префикс класса или S как префикс структуры. Мы решили - это просто больше набирать текст.
Пример:
class MyClass
{
};
struct MyStruct
{
};
класс или структура
В некоторых случаях трудно понять, если нам нужен класс или структура. Если структура просто хранит некоторые сгруппированные данные - это struct
. Если структура хранит данные и имеет методы - это class
. Исключительными методами являются конструкторы, деструкторы и операторы сравнения.
Пример:
class MyClass
{
public:
MyClass();
~MyClass();
void SetValue(int value);
int GetValue();
void PrintValue();
private:
int m_value;
};
struct MyStruct
{
MyStruct();
~MyStruct();
int value;
};
Тип имена
начинаться с заглавной буквы и имеют прописную букву для каждого слова (не подчеркивание).
Например:
typedef std::string String;
typedef std::vector<String> StringVector;
Типы переменных
Используйте наши собственные предопределенные типы, мы имеем:
typedef std::string String;
typedef std::vector<String> StringVector;
typedef unsigned char Byte;
typedef std::vector<Byte> ByteVector;
//etc.
Variable именование
Начните с нижней буквой и имеют заглавная буква для каждого нового слова (без подчеркивания).
Пример:
String messageLicenseExpired = "Your product version is expired, please...";
int importantNumber = 13;
класса переменных называющие
начинается с префикса m_ то слово начинается с буквы нижнего и имеют прописную букву для каждого слова (не подчеркивание).
Пример:
int m_myVariable;
int m_otherVariable;
Константы
Используйте все прописные с подчеркиванием.
Пример:
const String PRODUCT_NAME = "our product";
const Byte IMPORTANT_NUMBER = 13;
Константа или препроцессор
Если значение будет проверено с помощью #ifdef
или некоторых других, то оно должно быть препроцессор определения. В противном случае это const
.
Например:
#define FAILURE_FACTOR_FOR_DEBUG 50
const int MAGIC_NUMBER = 5;
//some code...
String newString = someString.substr(MAGIC_NUMBER);
//some code...
//not the best example, but I think it is understandable.
#ifdef _DEBUG
int someValue = FAILURE_FACTOR_FOR_DEBUG;
#else
int someValue = 0;
#end
Функции и методы именования
начинаться с заглавной буквы и имеют прописную букву для каждого слова (не подчеркивание).
Например:
int CalculateSometing (int n);
void ToUpper (String& someStr);
Брекеты
Скобы должны всегда идти в новую строку, за исключением инициализации.
Пример:
int arr[] = {1, 2, 3};
if (arr[0] > 10)
{
//do something
}
else
{
//do something else
}
еще
else
принадлежит к новой линии, см предыдущий пример.
, если заявление и брекеты
Даже одну строку кода после if
или else
должна быть приложена.
Пример:
if (someInt > 100)
{
someInt = 100;
}
else
{
someInt /= 2;
}
Методы называя
Нет места вокруг стрелки и точки.
Пример:
Object obj;
Object* oPtr = new Object();
obj.Method();
obj->Method();
Header файлы
- использовать
#pragma once
вместо опредиления охранников. (#pragma once
не является стандартным, поэтому в некоторых компиляторах необходимо установить защитные ограждения) - Один заголовок только для одного класса.
- Заголовочные файлы только для определений. Инструкции по выполнению должны быть связаны с соответствующим файлом
cpp
, даже если он содержит геттер или сеттер. Это связано с тем, что изменения заголовка приводят к длительной компиляции.
указатели и ссылки
Используйте ссылки вместо указателя, если это возможно. Если возможно, передайте параметр в качестве ссылки (для объектов), предпочитайте передавать в качестве ссылки const
, если значение не будет изменено.
Пример:
String ToUpper(String str); //bad
String ToUpper(String& str); //better
String ToUpper(const String& str); //best
void ToUpper(String& str); //also solution
обработки
Если функция может не ошибка, он должен вернуть bool
значение true
для успеха и false
неудачи. Для классов метод GetLastError()
является обязательным. Для функции, которая может выйти из строя, код ошибки должен быть возвращен через дополнительный параметр, например. bool Function(int param, int* errorCode = NULL)
Также мы решили не использовать исключения в нашем коде.
классовая структура
В файле заголовка первые публичные методы (конструкторы и деструкторы на них сверху), защищенные методы, защищенные переменные, частные методы, частные переменные. Нет общедоступных переменных, используйте геттеры и сеттеры.
Пример:
class MyClass
{
public:
MyClass();
~MyClass();
int GetPrivateValue();
void SetPrivateValue(int value);
int GetProtectedValue();
void SetProtectedValue(int value);
protected:
void SomeMethod();
int m_protectedValue;
private:
void SomePrivateMethod();
int m_privateValue;
};
Форматирование
- использования Выравнивание 4 пробелов или вкладки.
- Длинные обертывания линий, больше не линии, а затем 120 символов.
документирован код
Комментарии всегда приветствуются, но лучший выбор, чтобы дать имя для переменных и функций, что объясняет все.
Пример:
void Function (const String& str, const String& str2, StringVector& vect); //very bad
//This functions tokenize string, str is input string, str2 is delimiters string, vect output
void Function (const String& str, const String& str2, StringVector& vect); //quite bad
void Tokenize (const String& inputString, const String& delimiters, StringVector& output); //good, anyway comments using this declaration also welcome.
& и * Положение
Написать &
и *
только после того, как тип переменной.
Пример:
String* strPtr;
String& strRef;
Это все, что мы решили использовать, вопрос, разве мы не пропустили что-то? Кроме того, есть ли что-нибудь глобально неприемлемо?
Не стесняйтесь комментировать и спрашивать, не ясно ли что-то, почему мы выбрали некоторые.
Надеюсь, это будет полезно для последних читателей.
Я не читал все, но я укажу, что использование капитала первых слева переменных не стандарт. Это делает их трудно отличить от классов. Обычный стандарт - это начало в нижнем регистре, затем camelCase – Dave
Также ваш последний комментарий, я недавно переключился на стиль 'String * ptr'. Нет аргументов против него, если вы никогда не инициализируете несколько переменных в одной строке (что в большинстве случаев я считаю неудачным) – Dave
Что касается обработки ошибок, если вы не против исключений (понятных), используйте их. Нет смысла иметь специальные параметры ошибки и последние методы ошибок, когда улов будет достаточным. – Dave