1、行长度(有争议)
每一行代码字符数不超过 80。
2、非 ASCII 字符
尽量不使用非 ASCII 字符,使用时必须使用 UTF-8 格式。
3、空格vs.制表位(Space vs. Tabs)
只使用空格,每次缩进2个空格。
使用空格进行缩进,不要在代码中使用tabs,设定编辑器将tab转为空格。
4、函数声明与定义
返回类型和函数名在同一行,合适的话,参数也在同一行。函数看上去这样:
RetureType ClassName::FunctionName(Type par_name1, Type par_name2){
DoSomething();
...
}
若同一行文本较多,容不下所有参数:
RetureType ClassName::ReallyLongFunctionName(Type par_name1,
Type par_name2,
Type par_name3) {
DoSomething();
...
}
甚至连第一个参数都放不下:
ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
Type par_name1, //4个空格缩进
Type par_name2,
Type par_name3) {
DoSomething();
...
}
注意以下几点:
1)返回值总是和函数名在同一行;
2)左圆括号总是和函数名在同一行;
3)函数名和左圆括号间没有空格;
4)圆括号与参数间没有空格;
5)左大括号总是在最后一个参数同一行的末尾处;
6)右大括号总是单独位于函数的最后一行;
7)右圆括号和左大括号之间总是有一个空格;
8)函数声明和实现处的所有形参名称必须一致;
9)所有形参应尽可能对齐;
10)缺省缩进2个空格;
11)独立封装的参数保持4个空格的缩进。
如果函数为const的,关键字const应与最后一个参数位于同一行。这里指const位于函数名后的情况。注意:const位于函数名后,表示函数不能改变其中数据成员的值;const位于函数名前表示返回值是const类型,返回值不能做表达式左值。
// Everything in this function signature fits on a single line
ReturnType FunctionName(Type par) const {
...
}
// This function signature requires multiple lines, but
// the const keyword is on the line with the last parameter. ReturnType ReallyLongFunctionName(Type par1,
Type par2) const {
...
}
如果有些参数没有用到,在函数定义处将参数名注释起来:
// Always have named parameters in interfaces.
class Shape {
public:
virtual void Rotate(double radians) = 0;
};
// Always have named parameters in the declaration.
class Circle : public Shape {
public:
virtual void Rotate(double radians);
};
// Comment out unused named parameters in definitions.
void Circle::Rotate(double /*radians*/) {}
// Bad - if someone wants to implement later, it's not clear what the
// variable means.
void Circle::Rotate(double) {}
5、函数调用
尽量放在同一行,否则,将实参封装在圆括号中。
函数调用遵循如下形式:
bool retval = DoSomething(argument1, argument2, argument3);
如果同一行放不下,可断为多行,后面每一行都和第一个实参对齐,左圆括号后和右圆括号 前不要留空格:
bool retval = DoSomething(averyveryveryverylongargument1,
argument2, argument3);
如果函数参数比较多,可以出于可读性的考虑每行只放一个参数:
bool retval = DoSomething(argument1,
argument2,
argument3,
argument4);
如果函数名太长,以至于超过行最大长度,可以将所有参数独立成行:
if (...) {
...
...
if (...) {
DoSomethingThatRequiresALongFunctionName(
very_long_argument1, // 4 space indent
argument2,
argument3,
argument4);
}
6、条件语句
更提倡不在圆括号中添加空格,关键字else另起一行。但是以一致性为主。
if (condition) { //括号内没有空格
... //2个空格缩进
} else { //else与右大括号在同一行
...
}
注意if和左圆括号间有个空格,右圆括号和左大括号间也有个空格:
if(condition) { //Bad,IF后没有空格
if (condition){ //Bad,大括号前没有空格
if(condition){ //Doubly bad.
if (condition) { //Good
条件语句没有else分支且语句简单时,可以写在同一行:
if (x == kFoo) return new Foo();
if (x == kBar) return new Bar();
但是如果条件语句有else分支就不能写在同一行:
//不允许这样
if (x) DoThis();
else DoThat();
如果语句中哪一分支使用了大括号,则其他部分也必须使用:
if (condition) {
foo;
} else {
bar;
}
7、循环和开关选择语句
switch语句如果有不满足case枚举条件的值,要总是包含一个default(若有输入值没有case处理,编译器将报警)。如果default永不会执行,可以简单的使用assert(断言);
switch (var) {
case 0: { //2个空格缩进
... //4个空格缩进
break;
}
case 1: {
...
break;
}
default: {
assert(false);
}
}
空循环体应该使用 {} 或者 continue,而非一个分号:
while (condition) {
...
}
for (int i = 0; i < kSomeNumber; ++i) {} //Good, 空循环体
while (condition) continue; //Good,continue
while (condition); //Bad
8、指针和引用表达式
句点(.)或箭头(->)前后不要有空格,指针/地址操作符(*、&)后不要有空格。
下面是正确范例:
x = *p;
p = &x;
x = r.y;
x = r->y;
注意:
1) 在访问成员时,句点或箭头前后没有空格;
2) 指针操作符*或&后没有空格。
在声明指针变量或参数时,星号与类型或变量名紧挨都可以:
// These are fine, space preceding.
char *c;
const string &str;
// These are fine, space following.
char* c; // but remember to do "char* c, *d, *e, ...;"!
const string& str;
char * c; // Bad - spaces on both sides of *
const string & str; // Bad - spaces on both sides of &
9、布尔表达式
如果一个布尔表达式超过标准行宽(80 字符),如果断行要统一一下。
下例中,逻辑与(&&)操作符总位于行尾:
if (this_one_thing > this_other_thing &&
a_third_thing == a_fourth_thing &&
yet_another & last_one) {
...
}
10、函数返回值
return 表达式中不要使用圆括号。
return x; // not return(x);
11、变量及数组初始化
选择=还是()。
需要做二者之间做出选择,下面的形式都是正确的:
int x = 3;
int x(3);
string name("Some Name");
string name = "Some Name";
12、预处理指令
预处理指令不要缩进,从行首开始。
即使预处理指令位于缩进代码块中,指令也应从行首开始。
// Good - directives at beginning of line
if (lopsided_score) {
#if DISASTER_PENDING // Correct -- Starts at beginning of line
DropEverything();
#endif
BackToNormal();
}
13、类格式
声明属性依次序是 public:、protected:、private:,每次缩进 1 个空格
类声明的基本格式如下:
class MyClass : public OtherClass {
public: // 注意缩进1个空格
MyClass(); // Regular 2 space indent.
explicit MyClass(int var);
~MyClass() {}
void SomeFunction();
void SomeFunctionThatDoesNothing() {
}
void set_some_var(int var) { some_var_ = var; }
int some_var() const { return some_var_; }
private:
bool SomeInternalFunction();
int some_var_;
int some_other_var_;
DISALLOW_COPY_AND_ASSIGN(MyClass);
};
注意:
1) 所以基类名应在 80 列限制下尽量与子类名放在同一行;
2) 关键词 public:、protected:、private:要缩进 1 个空格;;
3) 除第一个关键词(一般是 public)外,其他关键词前空一行,如果类比较小的话也可以不空;
4) 这些关键词后不要空行;
5) public 放在最前面,然后是 protected 和 private;
14、初始化列表
构造函数初始化列表放在同一行或按四格缩进并排几行。
// When it all fits on one line:
MyClass::MyClass(int var) : some_var_(var), some_other_var_(var + 1) {
}
或者
// 当需要多行时, 注意将冒号放在初始化的第一行,且4个空格缩进
// the first initializer line:
MyClass::MyClass(int var)
: some_var_(var), // 4 space indent
some_other_var_(var + 1) { // lined up
...
DoSomething();
...
}
15、命名空间格式化
命名空间内容不缩进。
命名空间不添加额外缩进层次,例如:
namespace {
void foo() { // Correct. No extra indentation within namespace.
...
}
} // namespace
16、水平留白
水平留白的使用因地制宜。不要在行尾添加无谓的留白。
普通:
void f(bool b) { // 大括号前应该有留白
...
int i = 0; // 分号前通常不加留白
int x[] = { 0 }; // 大括号内的数组初始化有留白
int x[] = {0}; // 可以. 如果大括号内不留白,则注意前后都不留白
// 继承和初始化列表中冒号前后的留白
class Foo : public Bar {
public:
// For inline function implementations, put spaces between the braces
// and the implementation itself.
Foo(int b) : Bar(), baz_(b) {} // 空括号不留白
void Reset() { baz_ = 0; } // 执行语句与大括号留白
...