C++ нотация с использованием только маленьких букв
Е.А.Охотников
2002.04.09, 2003.06.23, 2004.03.03, 2004.10.12, 2005.01.10
Маленькими буквами, отдельные слова разделяются подчеркиванием.
Заголовочные файлы имеют расширение .hpp
Файлы реализации имеют расширение .cpp
header_file.hpp source_file.cpp my_complex_class.hpp my_complex_class.cpp
Если в директиве include нужно указать имя файла вместе с именами каталогов, то нужно использовать прямые косые:
#include <so_lib/h/so_lib.hpp> #include <auto_ptr_2/h/vect_ptr.hpp> #include <simexpl_1/delarue_2/card_type/h/card_type.hpp>
При использовании #include отдельные логически связанные группы заголовочных файлов нужно отделять пустой строкой:
#include <stdafx.h> #include <string> #include <vector> #include <assert.h> #include <string.h> #include <stdio.h> #include <ctype.h> #include <so_lib/h/so_lib.hpp> #include <auto_ptr_2/h/vect_ptr.hpp> #include <auto_ptr_2/h/obj_ptr.hpp> #include <simexpl_1/h/log_macros.hpp> #include <simexpl_1/h/card_representation.hpp> #include <simexpl_1/h/reader_thread.hpp> #include <simexpl_1/h/card_info.hpp> #include <simexpl_1/delarue_2/card_type/h/card_type.hpp>
Пишутся только маленькими буквами. Использование заглавных букв возможно только для значащих аббревеатур (например, SMNP, HTTP, SMTP, POP3 и т.д.), хотя аббревеатуры так же можно записывать маленькими буквами).
Каждое значимое слово отделяется подчеркиванием.
Если имя состоит из нескольких самостоятельных названий, то названия могут разделяться дополнительным подчеркиванием.
После закрывающей фигурной скобки пространства имен желательно указывать в комментарии к какому пространству имен относится эта скобка.
namespace oess_sequence_1 { namespace impl { } /* namespace impl */ } /* namespace oess_sequence_1 */
Завершаются суффиксом _t.
Пишутся только маленькими буквами. Использование заглавных букв возможно только для значащих аббревеатур (например, SMNP, HTTP, SMTP, POP3 и т.д.), хотя аббревеатуры так же можно записывать маленькими буквами).
Каждое значимое слово отделяется подчеркиванием.
Если имя состоит из нескольких самостоятельных названий, то названия могут разделяться дополнительным подчеркиванием.
Для типа указателя на функцию должен использоваться префикс pfn.
Для типа исключения может использоваться суффикс _ex_t.
struct my_struct_t {...}; typedef unsigned char uint8_t; class io_subsystem_t { ... }; class io_subsystem_iostream_t : public io_subsystem_t { ... }; class io_subsystem_socket_tcp_t : public io_subsystem_t { ... }; class io_subsystem_socket_udp_t : public io_subsystem_t { ... }; typedef uint8_t ( * pfn_some_function_t )(); class out_of_range_t { ... }; class file_not_found_ex_t : public std::exception { ... };
Начинаются с маленькой буквы.
Пишутся только маленькими буквами. Использование заглавных букв возможно только для значащих аббревеатур (например, SMNP, HTTP, SMTP, POP3 и т.д.), хотя аббревеатуры так же можно записывать маленькими буквами).
Каждое значимое слово отделяется подчеркиванием.
Если имя состоит из нескольких самостоятельных названий, то названия могут разделяться дополнительным подчеркиванием.
Если не получает аргументов, то описывается как f(), а не как f( void ).
Может иметь суффикс _, для того, чтобы отличать от методов.
Описание возвращаемого значение делается на отдельной строке (очень полезно если тип возвращаемого значения имеет длинное имя).
void some_fuction(); void init_io_subsystem_(); void init_io_subsystem__iostream_( iostream & o );
Начинаются с маленькой буквы.
Пишутся только маленькими буквами. Использование заглавных букв возможно только для значащих аббревеатур (например, SMNP, HTTP, SMTP, POP3 и т.д.), хотя аббревеатуры так же можно записывать маленькими буквами).
Каждое значимое слово отделяется подчеркиванием.
Если имя состоит из нескольких самостоятельных названий, то названия могут разделяться дополнительным подчеркиванием.
Если не получает аргументов, то описывается как m(), а не как m( void ).
Пары методов для получения и изменения какого-либо значения можно именовать двумя способами:
const std::string & query_font_name() const; void set_font_name( const std::string & name );
const std::string & font_name() const; void set_font_name( const std::string & name );Данный способ предпочтительнее, т.к. используются более короткие имена при обращении к getter-ам.
Описание возвращаемого значение делается на отдельной строке (очень полезно если тип возвращаемого значения имеет длинное имя).
class some_class_t { public : void some_method(); void init(); virtual void init_io_subsystem(); static void init_io_subsystem__iostream( iostream & o ); };
Начинаются с маленькой буквы.
Пишутся только маленькими буквами. Использование заглавных букв возможно только для значащих аббревеатур (например, SMNP, HTTP, SMTP, POP3 и т.д.), хотя аббревеатуры так же можно записывать маленькими буквами).
Каждое значимое слово отделяется подчеркиванием.
Если имя состоит из нескольких самостоятельных названий, то названия могут разделяться дополнительным подчеркиванием.
void some_fuction_( some_type_t & some_argument ) { my_class_t my_object; io_subsystem_iostream_t iostream_subsystem; }
Могут начинаются с префикса g_.
В остальном должны следовать правилам именование переменных.
my_class_t g_my_class; io_subsystem_socket_tcp_t g_subsys_sock_TCP; io_subsystem_socket_udp_t g_subsys_sock_UDP;
Префикс g_ не обязателен, если имя переменной однозначно разрешается в рамках текущего контекста.
namespace cfg { // Глобальная переменная. configuration_t current; } // Использование глобальной переменной. configuration_t my_config = cfg::current;
Начинаются с префикса m_.
В остальном должны следовать правилам именование переменных.
struct info_t { int m_id; int m_type; int m_priority; char m_short_name; std::string m_full_name; }; class my_class_t { protected : std::string m_full_name; static io_sybsystem_t m_io_subsys; };
Венгерская нотация в именах переменных НЕ ИСПОЛЬЗУЕТСЯ.
Могут начинатся с префикса c_. Префикс можно опускать, если константы определяются в контексте, исключающем их двоякое толкование. Например, в пространстве имен, предназначенном для описания кодов ошибок, если все коды представляются константами. В этом случае префикс c_ избыточен.
В остальном должны следовать правилам именование переменных.
const size_t c_max_size = 15; const char * c_default_file_name = "noname.cpp"; namespace error_code { const int no_error = 0; const int not_found = 1; const int bad_argument = 2; }
Могут начинатся с префикса e_. Префикс можно опускать, если перечисление определяются в контексте, исключающем его двоякое толкование. Например, в каком-либо классе. В этом случае префикс e_ избыточен, поскольку доступ к элементам перечисления осуществляется через имя класса.
В остальном должны следовать правилам именование переменных.
Если в нутри одного блока (например, описания класса) определяется несколько перечислений, то каждый элемент перечисления может иметь специальный префикс, уникальный для перечисления.
enum error_t { e_none, e_bad_argument, e_io_error, e_no_memory }; class gsm_sms_text_t { public : enum data_coding_scheme_t { default_coding_scheme, general_coding_scheme, sim_specific_coding_scheme }; enum default_coding_scheme_t { def_default_alphabet = 0x01, def_unicode_alphabet = 0x03, def_byte_alphabet = 0x07, def_sim_specific = 0x04 }; enum general_coding_scheme_t { gen_default_alphabet = 0x10, gen_unicode_alphabet = 0x20, gen_byte_alphabet = 0x40, gen_sim_specific = 0x60 }; };
Длина строки не должна превышать 70 символов. Оптимальная длина 60-65 символов при размере табуляции 4 символа.
Все отступы должны формироваться только при помощи табуляции.
Если строка становится слишком длинной, то продолжение пишется в новой строке с отступом в одну табуляцию или две табуляции. В некоторых случаях (например, в сложных условях операторов if, while, for и т.д. за которыми идет всего один оператор, более удобно использовать отступ в две табуляции).
Не нужно выравнивать продолжение строки по каким-либо открывающим круглым или квадратным скобкам, началу вызова функции, началу варианта case в switch и т.д. Ниже перечислены НЕПРАВИЛЬНЫЕ примеры:
// Неправильно void some_class_t::some_method( some_type1_t & arg_type1, some_type2_t & arg_type2 ); // Неправильно if( 0 != ( my_file = fopen( file_name_manager->query_file_name( my_file_type ), file_name_manager->query_open_mode() ) ) ) // Неправильно i += my_data[ my_cross_ref_data[ j * query_line() + k * query_column() ] + delta ]; // Неправильно inline type_with_long_name_t * some_inline_fuction( int arg ) { return new type_with_long_name_t( arg ); } // Неправильно switch( operation_type ) { case c_op_type1 : { call_op_type1_handler(); break; } case c_op_type2 : { call_op_type2_handler(); break; } }
Правильный формат отступов определяется тем, что чтение происходит сверху вниз и слева направо. При переходе на новую строку глазам проще вернуться в крайнюю левую позицию, чем на произвольную позицию в центре или в правом конце строки.
Для открывающих и закрывающих скобок возможны два подхода:
Правильные варианты (с использованием отступа в одну табуляцию):
void some_class_t::some_method( some_type1_t & arg_type1, some_type2_t & arg_type2 ); if( 0 != ( my_file = fopen( file_name_manager->query_file_name( my_file_type ), file_name_manager->query_open_mode() ) ) ) i += my_data[ my_cross_ref_data[ j * query_line() + k * query_column() ] + delta ]; inline type_with_long_name_t * some_inline_fuction( int arg ) { return new type_with_long_name( arg ); } // Или inline type_with_long_name_t * some_inline_fuction( int arg ) { return new type_with_long_name( arg ); } // Или inline type_with_long_name_t * some_inline_fuction( int arg ) { return new type_with_long_name( arg ); } // Или inline type_with_long_name_t * some_inline_fuction( int arg ) { return new type_with_long_name( arg ); } switch( operation_type ) { case c_op_type1 : { call_op_type1_handler(); } break; case c_op_type2 : { call_op_type2_handler(); } break; } // Или switch( operation_type ) { case c_op_type1 : { call_op_type1_handler(); } break; case c_op_type2 : { call_op_type2_handler(); } break; } // Или switch( operation_type ) { case c_op_type1 : { call_op_type1_handler(); } break; case c_op_type2 : { call_op_type2_handler(); } break; } // Или switch( operation_type ) { case c_op_type1 : { call_op_type1_handler(); } break; case c_op_type2 : { call_op_type2_handler(); } break; }
В этих случаях удобно делать отступ в две табуляции:
// Здесь сразу видно, что throw не относиться к условию if. if( trace_no != config.trace_mode() && trace_last != config.trace_mode() && trace_all != config.trace_mode() ) throw std::logic_error( "unsupported trace mode" ); // Здесь сразу видно, где находиться тело for. for( my_object_map_t::const_iterator it = m_map.begin(); it != m_map.end(); ++it ) it->second.do_calculation( config, params, result );
Пробелов должно быть как можно больше. Каждый значащий элемент выражения должен выделяться пробелами.
Не должно быть двух или более идущих подряд пробелов.
Не должно быть пробела между идентификатором (ключевым словом) и открывающей скобкой.
После открывающей и перед закрывающей скобкой должны быть пробелы. Исключением является приведение типа в стиле C.
void my_func_( file_name_manager_t * file_name_manager, void * data ) { FILE * my_file; if( 0 != ( my_file = fopen( file_name_manager->query_name( c_my_file_name ), file_name_manager->query_open_mode( c_my_open_mode ) ) ) ) { try { my_data_object_t * data_obj = (my_data_object_t *)data; data_obj->save_data( my_file ); } catch( invalid_data_t & x ) { } fclose( my_file ); } }
Комментарии не должны превышать максимальную длину строки.
Комментарии должны предшествовать описаниям и действиям, а не следовать за ними справа или снизу.
Многострочные коментарии должны использоваться для больших фрагментов поясняющего текста. Например для подробного описания назначения класса.
Для изъятия больших фрагментов кода при отладке нужно использовать не комментарии, а инструкции #if 0/#endif
В идеале, для нешаблонного класса, не описывающего доступных вложенных типов, должна использоваться только одна секция public и либо одна секция protected, либо одна секция private, либо одна секция protected и одна секция private.
При реализации класса сначала должны следовать объявления статических переменных, затем конструкторов и дейструкторов, затем остальных методов. Желательно, что-бы реализация методов соблюдала порядок декларации методов в описании класса (если это позволяет среда разработки).