[C++] 编程实践之1: Google的C++代码风格6:命名约定

##命名约定
最重要的一致性规则是命名管理。命名风格快速获知名字代表的是什么东西:类型?变量?函数?常量?宏…?甚至不需要去查找类型声明。我们大脑中的模式匹配引擎可以非常可靠的处理这些命名规则。

命名规则具有一定的随意性,但相比较个人喜好命名,一致性更重要。所以不管你怎么想,规则总是规则。
###通用命名规则

函数命名,变量命名,文件命名要有描述性,少用缩写。

尽可能给有描述性的命名,别心疼空间,毕竟让代码易于新读者理解很重要。不要用只有项目开发者能理解的缩写,也不要通过砍掉几个字母来缩写单词。

下面给出一些通用原则的示例:

int price_count_reader;		// 无缩写
int num_errors;				// "num"本来就很常见,可以缩写
int num_dns_connections;	// 人人都知道“DNS”是什么

下面的命名规则尽量避免:

int n;						// 莫名其妙
int nerr;					// 怪缩写
int n_comp_conns;			// 怪缩写
int wgc_connections;		// 只有贵团队知道这是什么东西
int pc_reader;				// "pc"有太多可能的解释了
int cstmr_id;				// 有删减若干字母

###文件命名
文件名要全部小写,可以包含下划线(_)或者连字符(-),按照项目约定来。如果没有项目约定,则“_”更好。可以接受的文件命名:

* my_useful_class.cc
* my-useful-class.cc
* myusefulclass.cc
* myusefulclass_test.cc // "_unittest"和"_regtest"已经弃用

C++文件要以.cc结尾(为什么不是.cpp呢?)。头文件以.h结尾。专门插入文本的文件则以.inc结尾,参见关于头文件的规则。

不要使用已经存在于/usr/include下的文件名(即编译器搜索系统头文件的路径),如db.h

通常应尽量让文件名更加明确。http\_server\_logs.h就比logs.h要好。定义类时文件名一般成对出现,如foo\_bar.hfoo\_bar.cc,对应于类FooBar

内联函数必须放在.h文件中,如果内联函数比较短, 就直接放在.h中。

###类型命名

类型名称的每个单词首字母均大写,不包含下划线:MyExcitingClassMyExcitingEnum

所有类型命名——类,结构体,类型定义(typedef),枚举——均使用相同约定。例如:

// classes and structs
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...

// typedefs
typedef hash_map<UrlTableProperties*, string> PropertiesMap;

// enums
enum UrlTableErrors { ...

###变量命名

变量名一律小写,单词之间用下划线连接。类的成员变量以下划线结尾,但结构体的就不用。例如:a_local_variable, a_struct_data_member, a_class_data_member_。

普通变量命名的举例:

string table_name;		// 可以——用下划线
string tablename;		// 可以——全小写
string tableName;		// 差——混合大小写(但这似乎是Java的命名规则?)

类数据成员:

  • 不管是静态的还是非静态的,类数据成员都可以和普通变量一样,但要接下划线。
class TableInfo {
...
private:
	string table_name_;                // 可以——尾后加下划线
	string tablename_;                 // 可以
	static Pool<TableInfo>* pool_;     // 可以
};

结构体变量:

  • 不管是静态的还是非静态的,结构体数据成员都可以和普通变量一样,不用像类那样接下划线。结构体与类的讨论请参考 结构体vs. 类 一节。
struct UrlTableProperties {
	string name;
	int num_entries;
}

全局变量:

  • 对全局变量没有特别要求,少用就好,但如果你要用,可以用g_或其它标志作为前缀,以便更好的区分局部变量。

###常量命名

在全局或者类里的常量名称前加k:kDaysInAWeek。且除去开头的k之外每个单词开头字母均大写。

所有编译时常量,无论是局部的,全局的还是类中的,和其他变量稍微区别一下。k后接大写字母开头的单词。这规则也适用于编译时的局部作用域常量,不过要按变量规则来命名也可以。

const int kDaysInAWeek = 7;

###函数命名

常规函数使用大小写混合,取值和设置函数则要求与变量名匹配:MyExcitingFunction(), MyExcitingMethod(), my_exciting_member_variable(), set_my_exciting_member_variable()。

常规函数:

  • 函数名的每个单词首字母大写,没有下划线。
  • 如果您的某函数出错时就要直接crash,那么就在函数名加上OrDie,但这函数本身必须集成在产品代码里,且平时也可能会出错。
AddTableEntry()
DeleteUrl()
OpenFileOrDie()

取值和设值函数:

  • 取值(Accessors)和设值(Mutators)函数要与存取的变量名匹配。这儿摘录一个类,num_entries_是该类的实例变量:
class MyClass {
public:
	...
	int num_entries() const { return num_entries_; }
	void set_num_entries(int num_entries) { num_entries_ = num_entries; }
private:
	int num_entries_;
};
  • 其它非常短小的内联函数名也可以用小写字母,例如,如果你在循环中调用这样的函数甚至都不用缓存器返回值,小写命名就可以接受。

###名字空间命名

名字空间用小写字母命名,并基于项目名称和目录结构:google_awesome_project。

关于名字空间的讨论和如何命名,参考 名字空间 一节。

###枚举命名

枚举的命名应当和常量或者宏一致:kEnumName或者ENUM_NAME。

单独的枚举值应该优先采用常量的命名方式,但宏方式的命名也可以接受。枚举名UrlTableErrors(以及AlternateUrlTableErrors)是类型,所以要用大小写混合的方式。

enum UrlTableErrors {
	kOK = 0,
	kErrorOutOfMemory,
	kErrorMalformatedInput,
};
enum AlternateUrlTableErrors {
	OK = 0,
	OUT_OF_MEMORY = 1,
	MALFORMATED_INPUT = 2,
};

2009年1月之前,我们一直建议采用宏的方式命名枚举值。由于枚举值和宏之间的命名冲突,直接导致了很多问题。由此,这里改为优先选择常量风格的命名方式。新代码应该尽可能优先使用常量风格。但是老代码没必要切换到常量风格,除非宏风格确实会产生编译期问题。

###宏命名

你并不打算使用宏,对吧?如果你一定要用,像这样命名:MY_MACRO_THAT_SCARES_SMALL_CHILDREN。

参考预处理宏。通常不应该使用宏,如果不得不用,其命名像枚举命名一样全部大写,使用下划线:

#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

###总结

  1. Google的命名约定有其高明之处,比如写了简单的类QueryResult,接着又可以直接定义一个变量query_result,区分度很好;再次,类内变量以下划线结尾,那么就可以直接传入同名的形参,比如TextQuery::TextQuery(std::string word) : word\_(word) {},其中word_自然是类内私有成员。
  2. 但是Google的命名规则也并不是完美的。事实上。例如在类内对于存取函数和其它函数采用不同的命名规则,会有时候令人迷惑(个人体验)。
  3. 其它命名规则也有其好处。例如CGAL类库中的命名规则我觉得就有如下好处:1)类成员变量以m_XX命名,在编程时只要打出m_,编辑器就可以自动弹出所有类成员变量可供选择;2)指针变量以pXXX开始,使人一看就知道该变量是指针类型的,而Google命名规则中没有区分指针变量和非指针变量;3)类成员函数的命名中单词之间以下划线分开,让人更容易看清(Google的命名规则中,如果函数名很长,需要读者仔细去辨认单词的组成,进而推断函数的作用)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值