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

来源:互联网 发布:视频去噪声软件 编辑:程序博客网 时间:2024/06/05 20:51

命名约定

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

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

通用命名规则

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

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

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

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 structsclass UrlTable { ...class UrlTableTester { ...struct UrlTableProperties { ...// typedefstypedef hash_map<UrlTableProperties*, string> PropertiesMap;// enumsenum 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
原创粉丝点击