C++编程规范和标准总结

时间:2021-05-02 14:33:50
  • 文件名:
    • 每个源代码文件应该有一个包含文件。每个包含文件描述了单个类或者多个类相结合的集合。一般头文件(.h,或.hpp)包含类的定义而不是实例。因此包含文件可以用在多个文件当中,源文件(.c,.或cpp)定义了编译时加载进内存的代码,它的实例化定义包含在头文件中,例如,一个类的定义应该包含在.hpp的包含文件中,一个全局变量应该在.cpp文件中实例化而不是.hpp文件中。用extern在头文件声明该全局变量。
    • 文件名应该能够反映出类名。通常类名都是大写字母开头,头文件名和源文件名一般用小写字母开头,如文件classBase.hpp将包含ClassBase{}的定义,classBase.cpp将包含该类函数的源代码。
    • 类名建议使用下面的格式命名: CXxClassID, 其中 "Xx" 指的是类的构件. (如. Mn-- main, Fm-- File manager, Cp --command processor) 每个单词的首字母大写,文件命名时,去除前面的“C”。
    • 当在一个头文件中包含另外一个头文件,不要包含全路径。这就避免了依赖于操作系统方法引用的目录路径创建的可移植性问题。应该使用编译器命令行标志来包含路径,如 –l/路径名。
    • 使用双引号“”来包含本地头文件,用<>来包含操作系统或编译器提供的头文件。
    • 为了方便使用脚本和make文件,文件名(目录路径)不应包含空格,括号“(”或其他操作系统部支持的非法字符。
  • 文件格式:
    • 行结束: 对于跨平台开发,应该去除”^M”字符。可以采用下面方法来去除:
      • Command: dos2unix filename.cpp
      • vim: :1,$ s/{ctrl-V}{ctrl-M}//
    • 如果使用MS/Visual studio ,在文件末尾加入包含至少一个空白的空行可以去除Unix下文件的文件结束标志“ctrl-D”。
  • 文件头:
    • 文件头应该包括版权声明,发布lincese.例如源代码在GUN license下发布的,需要声明。如果该文件包含公司的专有材料也应该声明。如果代码的license,copyright,发布用途不同,需要将这些代码划分到不同的文件中。
    • 注释应该放置在文件的最上面,用来说明该文件的名字和文件的内容。
  • 头文件:
    • C++ 经常用.hpp作为头文件名的后缀,而C用”.h”来作为头文件后缀。使用预定义宏来防止多次包含头文件。
#ifndef CLASS_NAME_H
#define CLASS_NAME_H
...
..
#endif

o   减少在头文件包含文件的个数,这样可以减少构建build时间。如果一个类的头文件不需要使用另外一个类的数据成员,可以采用calss className的方式来声明而不是包含该类的头文件。为了避免包含该类的全部声明,可以采用引用或指针或者前向声明该类。

o   前向声明的例子:class className;

注意:STL容器(std::list 和 std::vector)和typedefs不能使用前向声明,必须使用#include来包含。

o   如果C++中需要调用C函数,则在C头文件中应该使用下面的定义:

#ifdef __cplusplus
extern "C" {
#endif
...
..
C function declarations
..
...
#ifdef __cplusplus
}
#endif

o   避免使用在”.hpp”头文件中使用””namespace”。如果该文件包含在源代码中,使用者将无法使用定义在namespace中的变量并且将导致变量名冲突。

  • 类和结构体:
    • 类和结构体的定义一般使用大写字母开头。基类一般在类名后面添加”Base”作为后缀。在基类中的析构函数应该加上virtual。不是纯虚函数不需”0”.
class ClassName
{
public:
// Constructors:
// Destructor:
// Functions: modifiers (set), selectors (get)
// itterators:
// Attributes visible by scope of instantiation and use
protected:
// Attributes visible to descendents
private:
// Local attributes
};

                
  • 依赖于机器的代码应该放置在不同的文件中,易于移植。
  • 函数:
    • 函数体长度: 对于长度没有硬性的规定,只要容易理解就可以。如果不行,需要拆分成许多小的容易理解的部分。复杂的算法需要拆分成不超过50行的函数代码。
    • 在CPP中函数的定义应该和头文件中声明的函数顺序一致。
    • 行数名:使用相互补充的函数名: get/set, add/remove, create/destroy, start/stop, insert/delete, increment/decrement, begin/end, first/last, up/down, min/max, next/previous, open/close, show/hide, suspend/resume等。
    • 使用关键词 "const"来标志在函数中不能改变值的变量。
  • 使用规则:
    • 使用大写字母和下划线来区分宏常量和枚举。
    • 用单个大写字母来标志变量中一个新词、类名、函数名的开始。.
      如 thisIsAnExample
    • 函数名应该以小写字母开始。.
    • 类的定义使用大写字母开头。 “C”开头是匈牙利命名法,类的实例化应该以小写字母开头。如:
        CAbcXyz abcXyz
  • 不要使用在浮点数和0.0之间使用”==”。
  • 枚举:使用枚举应该使用它们声明的使用范围。
class ClassName
{
enum Month { January, February };
} Month tmpMonth = ClassName::January;

不要使用: Month tmpMonth = ClassName::Month::January;

  • C++语法格式:
    • 在下面这些操作符的两边应该加一个空格 +, -, <. >, =, ==, ...
    • 使用空格来缩进,不要使用Tabs,因为在不同的IDE和编辑器可能对Tabs的定义不同。
    • 将长的 Boolean表达式和参数分行并且使用适当的缩进。
if( longVariableNameAbc < longVariableNameDef&&
longVariableNameIjk < longVariableNameXyz)
{
}

分隔:

改变一个单词的字母为大写来区别一个新词的开始,这样可以时变量更短,是因为不使用“_”。Examples:

  • VariableForTheBlueTeam
  • variableForTheBlueTeamInstantiation
  • SPAM_Eliminator

C++ 变量命名约定和风格

"匈牙利" 前缀:.

m_
my_

Variable is a member of class. Some use the prefix "my" for class member variables and "our" for class member static variables. (Also "m" and "ms" for member and member-static) I have also seen the use of "_" as both a prefix and as a suffix to denote a class member variable. If using mixed languages remember that many FORTRAN compilers use a "_" suffix. Due to C++ name mangling there will probably be no conflict when using this notation. It is a common practice but theoretically could pose a problem with mixed languages.

_
(underscore)

  • Variable not intended to be exposed externally to the user. Internal workings only. Most often used by compiler and library authors.
  • Sometimes used (not preferred) as a suffix to repressent a class member variable.
  • Sometimes used as variable prefix for function arguments. When used with function arguments, it can represent in/out/inout:
    • _variable: Function input variable. More explicit: _inVariable
    • variable_: Function output variable. More explicit: outVariable_
    • _variable_: Input/output by function. More explicit: _inoutVariable_

Note: Dangerous when mixing C with FORTRAN as FUNCTION subroutines as suffixed with "_" in the object code. compiler flag "-fno-underscore".

__

Marks an use as extension to ANSI C++. Often not compiler independant. Usually reserved for use by compiler writers so it is best to avoid the double underscore.

Note: Be careful when mixing with FORTRAN as "__" is often generated in FORTRAN object symbol names. See the f77 compiler flag "-fno-second-underscore". Also used in Microsoft "Managed C++" directives.

a

array

c
n

count / number of

cb

count bytes / number of bytes

d

Data type double

dw

Data type double word

e

an enumeration or element of an array

b
f
is
has
should

boolean
(flag)
Example: isFound
Note: accessor functions can also use these same prefixes: bool isBoolean{ return mBoolean; }

g_

g gbl
Gbl

global variable. Also used is the "::" operator. i.e. ::variable

s
s_

Static variable

h

handle

i

index to an array or STL iterator

l

long data type. i.e. "long int"

p
ptr

pointer. Sometimes "Ptr" used as suffix.

lp

pointer to long data type

ch

C character

sz

Zero terminated string. char[]

str

C++ GNU template data type "string"

u

unsigned

ev

event

min

Lowest value

first

First element

lim

array limit

cmd

Command

cmp

Compare

init

Initialize

intr

Interrupt

msg

Message

rx

Recieve

tx

Transmit

C

Prefix for a Class name. Notation used by Microsoft MFC.
Example: CAbcXyz abcXyz
Note: The instatiation begins with a lower case letter while the class definition begins with a capital letter.

_t
_Type

Type definition (typedef - suffix). Prefix with capital letter.

_Enum

Enumeration type definition suffix.

_ds

Data structure suffix.

匈牙利命名例子::

  • ppachVarName: pointer to a pointer of an array of characters.
  • m_ppachVarName: class member variable which is a pointer to a pointer of an array of characters.

使用匈牙利命名法应该使代码更容易读而不是更复杂。有的人使用上面命名规则的一部分,如:m, _, g, s, e, b,i, n.