命名规范的整体原则
同一性 在编写一个子模块或派生类的时候,要遵循其基类或整体模块的命名风格,保持命名风格在整个模块中的同一性。
标识符组成 标识符采用英文单词或其组合,应当直观且可以拼读,可望文知意,用词应当准确。
最小化长度 && 最大化信息量原则 在保持一个标识符意思明确的同时,应当尽量缩短其长度。
避免过于相似 不要出现仅靠大小写区分的相似的标识符,例如“i”与“I”,“function”与“Function”等等。
避免在不同级别的作用域中重名 程序中不要出现名字完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但容易使人误解。
正确命名具有互斥意义的标识符 用正确的反义词组命名具有互斥意义的标识符,如:"nMinValue"和"nMaxValue","GetName()" 和 "SetName()" ....
避免名字中出现数字编号 尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导致产生无意义的名字(因为用数字编号最省事)。
类/结构
除了异常类等个别情况(不希望用户把该类看作一个普通的、正常的类之情况)外,C++类/结构
的命名应该遵循以下准则:
C++类/结构的命名 类的名称都要以大写字母“C”开头,后跟一个或多个单词。为便于界定,每个单词的首字母要大写。
推荐的组成形式 类的命名推荐用"名词"或"形容词+名词"的形式,例如:"CAnalyzer", "CFastVector" ....
不同于C++类的概念,传统的C结构体只是一种将一组数据捆绑在一起的方式。传统C结构体的命名规则为:
传统C结构体的命名 传统C结构体的名称全部由大写字母组成,单词间使用下划线界定,例如:"SERVICE_STATUS", "DRIVER_INFO" ....
函数
函数的命名 函数的名称由一个或多个单词组成。为便于界定,每个单词的首字母要大写。
推荐的组成形式 函数名应当使用"动词"或者"动词+名词"(动宾词组)的形式。例如:"GetName()", "SetValue()", "Erase()", "Reserve()" ....
保护成员函数 保护成员函数的开头应当加上一个下划线“_”以示区别,例如:"_SetState()" ....
私有成员函数 类似地,私有成员函数的开头应当加上两个下划线“__”,例如:"__DestroyImp()" ....
虚函数 虚函数习惯以“Do”开头,如:"DoRefresh()", "_DoEncryption()" ....
回调和事件处理函数 回调和事件处理函数习惯以单词“On”开头。例如:"_OnTimer()", "OnExit()" ....
变量
变量应该是程序中使用最多的标识符了,变量的命名规范可能是一套C++命名准则中最重要的部分:
变量的命名 变量名由作用域前缀+类型前缀+一个或多个单词组成。为便于界定,每个单词的首字母要大写。 对于某些用途简单明了的局部变量,也可以使用简化的方式,如:i, j, k, x, y, z ....
作用域前缀 作用域前缀标明一个变量的可见范围。作用域可以有如下几种:
前缀 说明 无 局部变量 m_ 类的成员变量(member) sm_ 类的静态成员变量(static member) s_ 静态变量(static) g_ 外部全局变量(global) sg_ 静态全局变量(static global) gg_ 进程间共享的共享数据段全局变量(global global)
除非不得已,否则应该尽可能少使用全局变量。
类型前缀 类型前缀标明一个变量的类型,可以有如下几种:
前缀 说明 n 整型和位域变量(number) e 枚举型变量(enumeration) c 字符型变量(char) b 布尔型变量(bool) f 浮点型变量(float) p 指针型变量和迭代子(pointer) pfn 特别针对指向函数的指针变量和函数对象指针(pointer of function) g 数组(grid) i 类的实例(instance) 对于经常用到的类,也可以定义一些专门的前缀,如:std::string和std::wstring类的前缀可以定义为"st",std::vector类的前缀可以定义为"v"等等。
类型前缀可以组合使用,例如"gc"表示字符数组,"ppn"表示指向整型的指针的指针等等。
推荐的组成形式 变量的名字应当使用"名词"或者"形容词+名词"。例如:"nCode", "m_nState","nMaxWidth" ....
常量
C++中引入了对常量的支持,常量的命名规则如下:
常量的命名 常量名由类型前缀+全大写字母组成,单词间通过下划线来界定,如:cDELIMITER, nMAX_BUFFER .... 类型前缀的定义与变量命名规则中的相同。
枚举、联合、typedef
枚举、联合及typedef语句都是定义新类型的简单手段,它们的命名规则为:
枚举、联合、typedef的命名 枚举、联合、typedef语句生成的类型名由全大写字母组成,单词间通过下划线来界定,如:FAR_PROC, ERROR_TYPE ....
宏、枚举值
宏、枚举值的命名 宏和枚举值由全大写字母组成,单词间通过下划线来界定,如:ERROR_UNKNOWN, OP_STOP ....
Windows类型
样本变量
MFC类
样本变量
HWND
hWnd;
CWnd*
pWnd;
HDLG
hDlg;
CDialog*
pDlg;
HDC
hDC;
CDC*
pDC;
HGDIOBJ
hGdiObj;
CGdiObject*
pGdiObj;
HPEN
hPen;
CPen*
pPen;
HBRUSH
hBrush;
CBrush*
pBrush;
HFONT
hFont;
CFont*
pFont;
HBITMAP
hBitmap;
CBitmap*
pBitmap;
HPALETTE
hPaltte;
CPalette*
pPalette;
HRGN
hRgn;
CRgn*
pRgn;
HMENU
hMenu;
CMenu*
pMenu;
HWND
hCtl;
CState*
pState;
HWND
hCtl;
CButton*
pButton;
HWND
hCtl;
CEdit*
pEdit;
HWND
hCtl;
CListBox*
pListBox;
HWND
hCtl;
CComboBox*
pComboBox;
HWND
hCtl;
CScrollBar*
pScrollBar;
HSZ
hszStr;
CString
pStr;
POINT
pt;
CPoint
pt;
SIZE
size;
CSize
size;
RECT
rect;
CRect
rect;
同一性 | 在编写一个子模块或派生类的时候,要遵循其基类或整体模块的命名风格,保持命名风格在整个模块中的同一性。
|
标识符组成 | 标识符采用英文单词或其组合,应当直观且可以拼读,可望文知意,用词应当准确。
|
最小化长度 && 最大化信息量原则 | 在保持一个标识符意思明确的同时,应当尽量缩短其长度。
|
避免过于相似 | 不要出现仅靠大小写区分的相似的标识符,例如“i”与“I”,“function”与“Function”等等。
|
避免在不同级别的作用域中重名 | 程序中不要出现名字完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但容易使人误解。
|
正确命名具有互斥意义的标识符 | 用正确的反义词组命名具有互斥意义的标识符,如:"nMinValue"和"nMaxValue","GetName()" 和 "SetName()" ....
|
避免名字中出现数字编号 | 尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导致产生无意义的名字(因为用数字编号最省事)。 |
类/结构
除了异常类等个别情况(不希望用户把该类看作一个普通的、正常的类之情况)外,C++类/结构 的命名应该遵循以下准则:
不同于C++类的概念,传统的C结构体只是一种将一组数据捆绑在一起的方式。传统C结构体的命名规则为:
|
函数
|
变量
变量应该是程序中使用最多的标识符了,变量的命名规范可能是一套C++命名准则中最重要的部分:
|
常量
C++中引入了对常量的支持,常量的命名规则如下:
|
枚举、联合、typedef
枚举、联合及typedef语句都是定义新类型的简单手段,它们的命名规则为:
|
宏、枚举值
|
Windows类型 | 样本变量 | MFC类 | 样本变量 |
HWND | hWnd; | CWnd* | pWnd; |
HDLG | hDlg; | CDialog* | pDlg; |
HDC | hDC; | CDC* | pDC; |
HGDIOBJ | hGdiObj; | CGdiObject* | pGdiObj; |
HPEN | hPen; | CPen* | pPen; |
HBRUSH | hBrush; | CBrush* | pBrush; |
HFONT | hFont; | CFont* | pFont; |
HBITMAP | hBitmap; | CBitmap* | pBitmap; |
HPALETTE | hPaltte; | CPalette* | pPalette; |
HRGN | hRgn; | CRgn* | pRgn; |
HMENU | hMenu; | CMenu* | pMenu; |
HWND | hCtl; | CState* | pState; |
HWND | hCtl; | CButton* | pButton; |
HWND | hCtl; | CEdit* | pEdit; |
HWND | hCtl; | CListBox* | pListBox; |
HWND | hCtl; | CComboBox* | pComboBox; |
HWND | hCtl; | CScrollBar* | pScrollBar; |
HSZ | hszStr; | CString | pStr; |
POINT | pt; | CPoint | pt; |
SIZE | size; | CSize | size; |
RECT | rect; | CRect | rect; |
一般前缀命名规范
前缀 | 类型 | 实例 |
C | 类或结构 | CDocument,CPrintInfo |
m_ | 成员变量 | m_pDoc,m_nCustomers |
变量命名规范
前缀 | 类型 | 描述 | 实例 |
ch | char | 8位字符 | chGrade |
ch | TCHAR | 如果_UNICODE定义,则为16位字符 | chName |
b | BOOL | 布尔值 | bEnable |
n | int | 整型(其大小依赖于操作系统) | nLength |
n | UINT | 无符号值(其大小依赖于操作系统) | nHeight |
w | WORD | 16位无符号值 | wPos |
l | LONG | 32位有符号整型 | lOffset |
dw | DWORD | 32位无符号整型 | dwRange |
p | * | 指针 | pDoc |
lp | FAR* | 远指针 | lpszName |
lpsz | LPSTR | 32位字符串指针 | lpszName |
lpsz | LPCSTR | 32位常量字符串指针 | lpszName |
lpsz | LPCTSTR | 如果_UNICODE定义,则为32位常量字符串指针 | lpszName |
h | handle | Windows对象句柄 | hWnd |
lpfn | callback | 指向CALLBACK函数的远指针 |
|
应用程序符号命名规范
前缀 | 符号类型 | 实例 | 范围 |
IDR_ | 不同类型的多个资源共享标识 | IDR_MAIINFRAME | 1~0x6FFF |
IDD_ | 对话框资源 | IDD_SPELL_CHECK | 1~0x6FFF |
HIDD_ | 对话框资源的Help上下文 | HIDD_SPELL_CHECK | 0x20001~0x26FF |
IDB_ | 位图资源 | IDB_COMPANY_LOGO | 1~0x6FFF |
IDC_ | 光标资源 | IDC_PENCIL | 1~0x6FFF |
IDI_ | 图标资源 | IDI_NOTEPAD | 1~0x6FFF |
ID_ | 来自菜单项或工具栏的命令 | ID_TOOLS_SPELLING | 0x8000~0xDFFF |
HID_ | 命令Help上下文 | HID_TOOLS_SPELLING | 0x18000~0x1DFFF |
IDP_ | 消息框提示 | IDP_INVALID_PARTNO | 8~0xDEEF |
HIDP_ | 消息框Help上下文 | HIDP_INVALID_PARTNO | 0x30008~0x3DEFF |
IDS_ | 串资源 | IDS_COPYRIGHT | 1~0x7EEF |
IDC_ | 对话框内的控件 | IDC_RECALC | 8~0xDEEF |
在16位操作系统中,近指针是16位的指针,它只表示段内的偏移地址,因而只能对64k字节数据段内地址进行存取,如 char near *p; p=(char near *)0xffff;
远指针是32位指针,它表示段地址:偏移地址,如定义远程指针p指向B500段的2号地址,即B500:0002,则可写作:char far *p; p=(char far *)0xB5000002; 因此,远指针可以进行跨段寻址,可以访问整个内存的地址。
在32位操作系统中,两种指针同义,均为32位。
Microsoft MFC宏命名规范
名称 | 类型 |
_AFXDLL | 唯一的动态连接库(Dynamic Link Library,DLL)版本 |
_ALPHA | 仅编译DEC Alpha处理器 |
_DEBUG | 包括诊断的调试版本 |
_MBCS | 编译多字节字符集 |
_UNICODE | 在一个应用程序中打开Unicode |
AFXAPI | MFC提供的函数 |
CALLBACK | 通过指针回调的函数 |
库标识符命名法
标识符 | 值和含义 |
u | ANSI(N)或Unicode(U) |
d | 调试或发行:D = 调试;忽略标识符为发行。 |
静态库版本命名规范
库 | 描述 |
NAFXCWD.LIB | 调试版本:MFC静态连接库 |
NAFXCW.LIB | 发行版本:MFC静态连接库 |
UAFXCWD.LIB | 调试版本:具有Unicode支持的MFC静态连接库 |
UAFXCW.LIB | 发行版本:具有Unicode支持的MFC静态连接库 |
动态连接库命名规范
名称 | 类型 |
_AFXDLL | 唯一的动态连接库(DLL)版本 |
WINAPI | Windows所提供的函数 |
Windows.h中新的命名规范
类型 | 定义描述 |
WINAPI | 使用在API声明中的FAR PASCAL位置,如果正在编写一个具有导出API人口点的DLL,则可以在自己的API中使用该类型 |
CALLBACK | 使用在应用程序回叫例程,如窗口和对话框过程中的FAR PASCAL的位置 |
LPCSTR | 与LPSTR相同,只是LPCSTR用于只读串指针,其定义类似(const char FAR*) |
UINT | 可移植的无符号整型类型,其大小由主机环境决定(对于Windows NT和Windows 9x为32位);它是unsigned int的同义词 |
LRESULT | 窗口程序返回值的类型 |
LPARAM | 声明lParam所使用的类型,lParam是窗口程序的第四个参数 |
WPARAM | 声明wParam所使用的类型,wParam是窗口程序的第三个参数 |
LPVOID | 一般指针类型,与(void *)相同,可以用来代替LPSTR |
C++以及MFC的命名规则基本上是符合匈牙利命名法的,匈牙利命名法是一种编程时的命名规范。基本原则是:变量名=属性+类型+对象描述,其中每一对象 的名称都要求有明确含义,可以取对象名字全称或名字的一部分。命名要基于容易记忆容易理解的原则。保证名字的连贯性是非常重要的。
举例来说,表单的名称为form,那么在匈牙利命名法中可以简写为frm,则当表单变量名称为 Switchboard时,变量全称应该为frmSwitchboard。这样可以很容易从变量名看出Switchboard是一个表单,同样,如果此变 量类型为标签,那么就应命名成lblSwitchboard。可以看出,匈牙利命名法非常便于记忆,而且使变量名非常清晰易懂,这样,增强了代码的可读 性,方便各程序员之间相互交流代码。
这种命名技术是由一位能干的Microsoft程序员查尔斯·西蒙尼(Charles Simonyi) 提出的,他出生在匈牙利。在 Microsoft 公司中和他一起工作的人被教会使用这种约定。这对他们来说一切都很正常。但对那些 Simonyi 领导的项目组之外的人来说却感到很奇特,他们认为这是死板的表达方式,甚至说带有这样奇怪的外观是因为它是用匈牙利文写的。从此这种命名方式就被叫做匈牙利命名法。
据说这种命名法是一位叫 Charles Simonyi 的匈牙利程序员发明的,后来他在微软呆了几年,于是这种命名法就通过微软的各种产品和文档资料向世界传播开了。现在,大部分程序员不管自己使用什么软件进行开发,或多或少都使用了这种命名法。这种命名法的出发点是把量名变按:属性+类型+对象 描述的顺序组合起来,以使程序员作变量时对变量的类型和其它属性有直观的了解,下面是HN变量命名规范,其中也有一些是我个人的偏向:
前缀 | 类型 | 描述 | 实例 |
arr | Array | 静态数组 | arrPoint |
b | BOOL | 布尔值 | bEnabled |
by | unsigned char(BYTE) | 8位无符号字符 | byWeek |
ch | Char | 8位字符 | chGrade |
tch | TCHAR | 如果是_UNICODE,为16位字符 | tchName |
i/n | Int | 整形(其大小依赖于操作系统) | iRange |
u | UINT | 无符号整形(其大小依赖于操作系统) | nLength |
us | unsigned short | 无符号短整形 | usPort |
w | WORD | 16位无符号值 | wParam |
l | LONG | 32位有符号整形 | loffset |
dw | DWORD | 32位无符号整形 | dwVolume |
f | Float | 4字节浮点数 | fHigh |
d | Double | 8字节浮点数 | dAmount |
cy | CURRENCY | 8字节货币类型 | cySell |
p | * | 指针 | pDoc |
lp | FAR * | 远指针 | lpDoc |
lpsz | LPSTR | 为32位字符串指针 | lpszName |
lpcsz | LPCSTR | 32位常量字符串指针 | lpcszName |
lpctsz | LPCTSTR | 如果_UNICODE定义,为32位常量字符串指针 | lpctszName |
bstr | BSTR | 带有4字节长度前缀的w_chart数组 | bstrMessage |
pbstr | BSTR* | BSTR数据类型指针 | pbstrMsg |
str | String | CString类型的字符串 | strMessage |
och | OLECHAR | OLECHAR字符类型 | ochX |
osz | OLECHAR* | OLECHAR字符串类型 | oszX |
var | VARIANT | VARIANT数据类型 | var |
pvar | VARIANT* | VARIANT数据类型指针 | pvar |
sa | SAFEARRAY | SAFEARRAY数据类型 | sa |
psa | SAFEARRAY* | SAFEARRAY数据类型指针 | psa |
dlg | CDialog | Windows对话框 | dlg |
stc | CStatic | Windows静态文本控件 | stc |
edt | Cedit | Windows编辑框控件 | edt |
lsb | CListBox | Windows列表控件 | lsb |
btn | CButton | Windows按钮控件 | btn |
scb | CScrollBar | Windows滚动条控件 | scb |
spn | CSpinButtonCtrl | Windowswe微调按钮控件 | spn |
tab | CTabCtrl | Windows选项卡控件 | tab |
rtf | CRichEditCtrl | Windows富文本编辑框控件 | rtf |
sld | CSliderCtrl | Window滑块控件 | sld |
list | ClistCtrl | Windows列表控件 | list |
tre | CtreeCtrl | Windows树形控件 | tre |
dtc | CDateTimeCtrl | Windows时间选取器控件 | dtc |
prg | CProgressCtrl | Windows进度指示器控件 | prg |
cbo | CComboBox | Windows组合框控件 | cbo |
ils | CImageList | Windows图像列表 | ils |
tlb | CToolBarCtrl | Windows工具条控件 | tlb |
mnu | Cmenu | Windows菜单控件 | mnu |
sta | CStatusBar | Windows状态条控件 | sta |
wnd | CWnd | Windows窗口 | wnd |
cx | X | Windows X坐标 | cx |
cy | Y | Windows Y坐标 | cy |
pt | Cpoint | Windows点阵 | hWnd |
size | Csize | Windows尺寸 | size |
rect/rc | Crect | Windows矩形 | rect |
pen | Cpen | Windows画笔 | pen |
br | Cbrush | Windows刷子 | br |
fnt | Cfont | Windows字体 | fnt |
cr | COLORREF | Windows颜色值RGB | cr |
PMp | Temp | 临时变量 | PMpBuff |
h | Handle | Windows对象句柄 | hWnd |
lpfn | Callback | 指向CALLBACK函数的远指针 | lpfnAbort |
it/iter | iterator | 迭代子 | it |
vect | std::vector | 标准模板库 | vect |
map | std:map | 标准模板库 | map |
deque | std:deque | 标准模板库 | deque |
list | std:list | 标准模板库 | list |
set | std:set | 标准模板库 | Set |
multiset | std:multiset | 标准模板库 | multiset |
multimap | std:multimap | 标准模板库 | multimap |
指针类型的变量,必须加上前缀"p",如:int* pnValue;。
全局(静态)变量的命名规则同第一条的规定,并且必须加上前缀"g_"。
类成员(静态)变量的命名规则同第一条的规定,并且必须加上前缀"m_"。
模块(函数/过程)内部的重要变量命名遵循第一条的规定。
模块(函数/过程)内部的静态变量命名遵循第一条的规定,并且加上前缀"s_"。
其余变量在不损害程序易读易懂原则的基础上酌情处理。这些变量通常是模块内的临时变量,如循环控制变量、数组的下标等,它们可用缩写进行简化处理,如:int i;。
宏(#define)或者常量修饰符(const):大写字母组成的名词词组,单词间用下划线作为连接符,如:#define INVALID_CLOSE 0; const double INVALID_CLOSE = double(0);。
枚举类型(enum):此时的命名规则同"变量命名的一般性规则",可参考MFC或ADO等的命名方式。
单词构成的动宾词组,每个单词首字母大写,其余字母小写。如:void DrawLine ( void );。
3.1.1.3 类命名规则
类的原型,是前缀"C"加单词构成的动宾词组,每个单词首字母大写,其余字母小写。如:class CStockPacket; class CPacket;。
类的实例变量,采用小写首字母缩写的方式定义,如:CStockPacket sp;。
在对类的成员变量和成员函数定义时,要加以分类,并界定相应的存取权限(参见表二:类成员的分类描述)
分类描述 | 存取权限(依实际应用而定) |
// Constructors | Public |
// Attributes | Private |
// Operations(对于com组件是//Methods) | Public |
// Overridables | Protected |
// Implementation | Private |
结构的原型采用组合词的方式定义,并且全部采用大写字符的形式。如:
typedef struct tagStockTrans
{
DWORD dwOpen;
...
} STOCKTRANS;
结构的实例变量,采用小写首字母缩写的方式定义,如:STOCKTRANS st;。