通用命名规则
命名应该要具有叙述的能力;避免使用缩写。
让一个名称具有越清楚的描述越好,包括原因在内。不要去想节省横向的空间,因为让你的程式码能够被新读者马上读懂这事重要得多。不要使用会让专案以外的读者看起来暧昧不明的缩写,以及不要利用删除一个单词之间的字母来制造缩写。那些可能对专案外但是具有一些相关领域知识的人来说看得懂的缩写还算可以接受。经验上来说,一个缩写如果有被列在维基百科(Wikipedia) 上的话,应该也可以接受。
int price_count_reader; // 不含缩写
int num_errors; // 「num」是很广泛运用的惯例
int num_dns_connections; // 大部份的人都知道「DNS」代表什么
int lstm_size; // 「LSTM」是机器学习 (Machine Learning) 领域中常见的缩写
注意有些普遍知道的缩写是可以接受的,像是i 代表叠代(iteration) 次数以及T 代表模板(template) 参数。
对于某些符号,这份指引建议对应的名称以大写字母作为开头,并在每一个单词的首字都使用大写字母(也就是所谓的驼峰式命名法)。在这种名称中如果出现缩写或者首字型缩写(acronyms, 译注:指的是用每个单字的第一个字母组成的缩写) 的话,偏好将该缩写或首字型缩写视为一个单词来处理(像是StartRpc(),而不是StartRPC() )。
模板参数应该要遵从所属种类的命名风格:型别模板参数应该遵从型别名称的规则,以及非型别模板参数应该要遵从变数名称的规则。
档案名称
档案名称应该完全使用小写,并可以包含底线( ) 或是横杠(-)。 关于这点请遵循各专案的惯例。 如果没有可以遵循且一致的本地模式,偏好使用。
一些可接受的档案名称范例:
- 我的有用类.cc
- 我的有用类.cc
- 我的有用类
- myusefulclass_test.cc // _unittest 与_regtest 两种写法都过时了
C++ 档案应该以.cc 结尾,同时标头档应该以.h 结尾。 依赖于在某个特定位置被文字引入的档案应该以.inc 结尾。
不要使用已经存在于/usr/include 的档名,像是db.h。
一般来说,应该要让你的档案名称非常精确。 例如,使用http_server_logs.h
而不是logs.h。 一个常见的状况是使用相同名称为一对档案命名,像是foo_bar.h 与foo_bar.cc 定义了名为FooBar 的类别。
型别名称
型别名称始于一个大写字母,并且每个单字的开头皆为大写字母,同时不包含底线:MyExcitingClass、MyExcitingEnum。
所有型别的名称- 类别、结构、型别别名、列举、型别模板参数- 都有相同的命名惯例。 型别名称始于一个大写字母,并且每个单字的开头皆为大写字母。 没有底线。 例如:
// 类别与结构
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...
// typedef
typedef hash_map<UrlTableProperties *, string> PropertiesMap;
// 使用别名
using PropertiesMap = hash_map<UrlTableProperties *, string>;
// 列举
enum UrlTableErrors { ...
变数名称
变数(包含函式的参数) 与资料成员的名称全部都使用小写,并使用底线隔开单字。 类别(但不包含结构) 的资料成员要另外在尾部加上底线。 例如,区域变数:a_local_variable、结构资料成员:a_struct_data_member、类别资料成员:a_class_data member。
常见的变数名称
可以接受的:
string table_name; // 可以 - 使用底线
string tablename; // 可以 - 全部小写
不可接受的:
string tableName; // 不好 - 大小写混合
类别资料成员
类别资料成员,包括静态(static) 与非静态的,都如同一般变数命名,但要在尾端加上底线。
class TableInfo {
...
private:
string table_name_; // 可以 - 尾端有底线
string tablename_; // 可以
static Pool<TableInfo>* pool_; // 可以
};
结构资料成员
类别资料成员,包括静态(static) 与非静态的,都如同一般变数命名。 他们不像类别一样要在尾端加上底线。
struct UrlTableProperties {
string name;
int num_entries;
static Pool<UrlTableProperties>* pool;
};
常数名称
使用constexpr 或const 宣告的变数,以及在程式全期数值皆是固定的变数,其名称应该以「k」为开头,并使用大小写混和的写法。 底线可以用在少数无法使用大小写明确分开的场合。例如:
const int kDaysInAWeek = 7;
const int kAndroid8_0_0 = 24; // Android 8.0.0
所有具备以上性质同时有静态储存期(例如静态变数与全域变数,详情请参照储存期) 的变数都应该这样命名。 这项惯例对其他储存种类的变数来说是选择性的(例如自动变数),其他情况应使用一般的变数命名规则。
函数名称
一般函式应使用大小写混和;存取子(Accessor) 与修改子(Mutator) 可以使用变数的方式命名。
一般来说,函式应以大写字母开头,并在每一个新单字的首字使用大写字母。
AddTableEntry()
DeleteUrl()
OpenFileOrDie()
(相同的命名规则也适用于类别与名称空间范围之中,那些作为API 的一部分释出的、或是意图使人看起来像是函数的常数。 因为这些常数其实是物件而不是函式这点算是不重要的实作细节。)
存取子与修改子(get
与set
函式) 可以用变数的方式命名。 他们的命名通常与实际的成员变数有关,但这并非必要。 例如:int count()
与void set_count(int count)
。
名称空间名称
名称空间全部使用小写。 最顶层的名称空间应使用基于专案名称的名字。 避免巢状名称空间以及与知名顶层名称空间的命名碰撞。
顶层的命名空间应通常使用专案名称或者开发该程式的团队名称。该名称空间中的程式码应该要放在与其名称空间的命名相符的资料夹中(或是子资料夹中)。
注意针对缩写名称的规则也如同变数一样适用于名称空间。名称空间中的程式码很少会需要提及名称空间的名称,所以通常没有使用缩写的必要。
避免使用名称与知名顶层名称空间冲突的巢状名称空间。名称空间的命名冲突可能因为命名查询规则造成意外的建置错误。特别是不要建立任何命名为std 的巢状名称空间。优先使用独特的专案ID (websearch::index、websearch::index_util),而不是容易发生冲突的名称,像是websearch::util。
对于internal 名称空间,请注意将其他程式码加入同样的internal 名称空间中会导致冲突(团队内部的辅助函式(Helper Functions) 倾向于且可能导致冲突)。在这种情况下,使用档名来建立一个独特的内部名称很有用(像是对frobber.h 中的程式使用websearch::index::frobber_internal)。
列举名称
使用常数命名: kEnumName
巨集名称
全部大写
#define ROUND(x) ...
#define PI_ROUNDED 3.0
如果你正在为类似于C 或C++ 内已经存在的实体进行命名,那么你可以遵循他们惯例的命名规则。
- bigopen()
-- 函式名称,跟随open() 的形式命名 - uint——
类型定义 - bigpos
-- struct 或class,跟随pos 的形式命名 - sparse_hash_map
-- 像是STL 的实体;跟随着STL 的命名惯例 - LONGLONG_MAX
-- 一个常数,像INT_MAX 一样命名
Struct与Class使用时机
在c++ 中struct 与class 的唯一差别
只是预设为public 或private 的不同而已
不过我们还是可以定义coding style
如果你的资料本身就是介面
那么你可以选择struct
或者选择class 然后将全部资料宣告为public
其余情况下你应该选择class 然后将所有资料都宣告为private
什么情况下资料本身就是介面呢?
那就是资料之间有性质相关
但是没有相依性的时候(也就是不会因为资料错误, 就导致整个型别坏掉, 如果会就建议用class 并用interface function包装变数操作)