编程规范(一):C/C++的命名原则


无以规矩,不成方圆。
符合规范的统一命名是程序编写的基本规矩之一。很多时候我们不愿意接手别人的代码,原因之一就是代码命名很乱;我们自己写代码时经常写到后面忘了前面,也有可能是我们没有养成规范的命名习惯。当写代码成为一种艺术的美时,这种美的最直接的体现就是其中变量函数等命名的规范性。

基本的命名原则

首先总结一下命名的基本原则,也就是“道”的层次。

方面 要求
同一性 一个方面是整个文件中命名的原则要相同,如变量、函数都按照相同的原则命名;另一方面是一个子模块或派生类中,要遵循其基类或整体模块的命名风格,保持命名风格在整个模块中的同一性。
标识符组成 命名应该由标识符组成,组成部分要确定,如变量类型前缀+变量信息英文缩写,且缩写统一采用动宾格式。
最小化长度AND最大化信息量原则 在保持一个标识符意思明确的同时,应当尽量缩短其长度。
避免在不同作用域中重名 程序中不要出现名字完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但容易使人误解。
正确命名具有互斥意义的标识符 用正确的反义词组命名具有互斥意义的标识符,如:“nMinValue"和"nMaxValue”,“GetName()” 和 “SetName()” …
避免名字中出现数字编号 尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。因为数字并传达不了有用信息。
禁止取单个字符作为变量名 i 、j 、k 作局部循环变量是允许的,其他则不允许。因为其很容易敲错(如i写成j),而编译时又检查不出来。
说明特殊约定或缩写 在源文件的开始之处,对文件中所使用的缩写或约定,特别是特殊的缩写,进行必要的注释说明。
特殊命名 除了编译开关/ 头文件等特殊应用,应避免使用_EXAMPLE_TEST_ 之类以下划线开始和结尾的定义。

常见的命名方法

目前业界共有四种常见的命名法则:驼峰命名法、匈牙利命名法、帕斯卡命名法和下划线命名法,其中前三种是较为流行的命名法。

驼峰命令法

正如它的名称所表示的那样,是指混合使用大小写字母来构成变量和函数的名字,其中第一个单词的首字母小写,其他单词的首字母大写,大写字母的位置如驼峰一样交替出现。下面是分别用骆驼式命名法和下划线法命名的同一个函数:

printEmployeePaychecks()print_employee_paychecks()

第一个函数名使用了驼峰命名法,函数名中的每一个逻辑断点都有一个大写字母来标记。第二个函数名使用了下划线法,函数名中的每一个逻辑断点都有一个下划线来标记。驼峰命名法近年来越来越流行了,在许多新的函数库和Microsoft Windows这样的环境中,它使用得当相多。另一方面,下划线法是C出现后开始流行起来的,在许多旧的程序和UNIX这样的环境中,它的使用非常普遍。

匈牙利命名法

广泛应用于象Microsoft Windows这样的环境中。Windows 编程中用到的变量(还包括宏)的命名规则为匈牙利命名法,这种命名技术是由一位能干的 Microsoft 程序员查尔斯-西蒙尼(Charles Simonyi) 提出的。
匈牙利命名法通过在变量名前面加上相应的小写字母的符号标识作为前缀,标识出变量的作用域、类型等。这些符号可以多个同时使用,顺序是先m_(成员变量)、再指针、再简单数据类型、再其它。这样做的好处在于能增加程序的可读性,便于对程序的理解和维护。
例如:m_lpszStr, 表示指向一个以0字符结尾的字符串的长指针成员变量。
匈牙利命名法关键是:标识符的名字以一个或者多个小写字母开头作为前缀;前缀之后的是首字母大写的一个单词或多个单词组合,该单词要指明变量的用途。

帕斯卡(pascal)命名法

与驼峰命名法类似,二者的区别在于:驼峰命名法是首字母小写,而帕斯卡命名法是首字母大写,如:

DisplayInfo();
string UserName;

二者都是采用了帕斯卡命名法。

三种命名规则的小结

MyData就是一个帕斯卡命名的示例;myData是一个驼峰命名法,它第一个单词的第一个字母小写,后面的单词首字母大写,看起来像一个骆驼;iMyData是一个匈牙利命名法,它的小写的i说明了它的型态,后面的和帕斯卡命名相同,指示了该变量的用途。

命名规范

现在讨论命名的具体操作,即“术”的层次。C++命名要采用匈牙利命名法,即要包括参数的类型信息。现在有很多人认为如今的IDE都提供了识别变量类型的功能,在变量命中体现变量类型属于画蛇添足的做法。以前我就被这种观点给洗脑了,结果在看程序的时候速度特别慢,每看到一个变量都要用鼠标放在其上面获取其变量类型!这时我才意识到:如果直接把变量类型放在变量名称中,就可以很大的提升看代码的速度和体验。因此,我认为命名要采用匈牙利法。

类/结构命名方法

除了异常类等个别情况(不希望用户把该类看作一个普通的、正常的类之情况)外,C++类/结构 的命名应该遵循以下准则1

准则 解释
C++类/结构的命名 类的名称都要以大写字母“C”开头,后跟一个或多个单词。为便于界定,每个单词的首字母要大写。
推荐的组成形式 类的命名推荐用"名词"或"形容词+名词"的形式,例如:“CAnalyzer”, “CFastVector” …
传统C结构体的命名 传统C结构体的名称全部由大写字母组成,单词间使用下划线界定,例如:“SERVICE_STATUS”, “DRIVER_INFO” …

不同于C++类的概念,传统的C结构体只是一种将一组数据捆绑在一起的方式。

函数命名方法

函数的命名应该尽量用英文(或英文缩写、中文全拼、中文全拼缩写)表达出函数完成的功能——函数名应准确描述函数的功能。遵循动宾结构的命名法则,函数名中动词在前,并在命名前加入函数的前缀,函数名的长度不得少于8个字母。函数名首字大写,若包含有两个单词的每个单词首字母大写。如果是OOP 方法,可以只有动词(名词是对象本身)。

函数的命名 函数的名称由一个或多个单词组成。为便于界定,每个单词的首字母要大写。
推荐的组成形式 函数名应当使用"动词"或者"动词+名词"(动宾词组)的形式。例如:“GetName()”, “SetValue()”, “Erase()”, “Reserve()” …
保护成员函数 保护成员函数的开头应当加上一个下划线“_”以示区别,例如:"_SetState()" …
私有成员函数 类似地,私有成员函数的开头应当加上两个下划线“__”,例如:"__DestroyImp()" …
虚函数 虚函数习惯以“Do”开头,如:“DoRefresh()”, “_DoEncryption()” …
回调和事件处理函数 回调和事件处理函数习惯以单词“On”开头。例如:"_OnTimer()", “OnExit()” …

变量命名原则

变量的命名规则要求用“匈牙利法”,即开头字母用变量的类型,其余部分用变量的英文意思、英文的缩写、中文全拼或中文全拼的缩写,要求单词的第一个字母应大写。即: 变量名=作用域前缀+变量类型+变量的英文意思(或英文缩写、中文全拼、中文全拼缩写)。对非通用的变量,在定义时加入注释说明,变量定义尽量可能放在函数的开始处。
作用域前缀标明一个变量的可见范围。作用域可以有如下几种:

前缀 说明
局部变量
m_ 类成员变量(member)
sm_ 静态类成员变量(static member)
g_ 全局变量(global)
s_ 静态变量(static)
sg_ 静态全局变量(static gloabl)
gg_ 进程间共享的共享数据段全局变量(global global)
c_ 常量变量(const)

类型前缀标明一个变量的类型,可以有如下几种:

前缀 说明
i 整数类型int
n 短整数类型short int
l 长整数类型long int
c 字符类型char
b 布尔型变量bool
f 单浮点型变量float
d 爽浮点型变量double
by 无符号字符unsigned char
w 无符号整型unsigned int(WORD)
s 字符串string
sz 用0结尾的字符串
p 指针变量,同理pp代表二重指针pointer

变量的英文意思,一般采用动词+宾语,或者形容词+名词进行表示。

函数参数命名规范2

  • 参数名称的命名参照变量命名规范。
  • 为了提高程序的运行效率,减少参数占用的堆栈,传递大结构的参数,一律采用指针或引用方式传递。
  • 为了便于其他程序员识别某个指针参数是入口参数还是出口参数,同时便于编译器检查错误,应该在入口参数前加入const标志。如:cmCopyString(const CHAR * c_szSource, CHAR * szDest)……

常量的命名方法

对常量(包括错误的编码)命名,规则如下:常量名由类型前缀+全大写字母组成,单词间通过下划线来界定,如:cDELIMITER, nMAX_BUFFER …

枚举、联合、typedef命名方法

枚举、联合及typedef语句都是定义新类型的简单手段,它们的命名规则为:类型前缀+大写名称。
对枚举类型(enum)中的变量,要求用枚举变量或其缩写做前缀。并且要求用大写。如:

enum cmEMDAYS
{
EMDAYS_MONDAY;
EMDAYS_TUESDAY;
……
};

对struct、union变量的命名要求定义的类型用大写。并要加上前缀,其内部变量的命名规则与变量命名规则一致。
结构一般用S开头,如:

struct ScmNPoint
{
int nX;//点的X位置
int nY; //点的Y位置
};

联合体一般用U开头,如:

union UcmLPoint
{
LONG lX;
LONG lY;
}

感谢博文1和博文2中博主的技术分享,从中受益良多。希望今后我能够按照自己总结的命名规范开始,开启自己的C++进阶之旅。

祝枫
2018年10月7日


  1. http://www.cnblogs.com/ggjucheng/archive/2011/12/15/2289291.html ↩︎

  2. https://www.cnblogs.com/wfwenchao/p/5209197.html ↩︎

猜你喜欢

转载自blog.csdn.net/Vince_ZHU/article/details/82891615