C++的风格大致上可以遵守 C 的风格,这里罗列了一些不同的地方:

命名

常量命名

所有编译时常量,无论是局部的,全局的还是类中的,和其他变量稍微区别一下. k 后接大写字母开头的单词:

1
const int kDaysInAWeek = 7;

枚举命名

枚举的命名应当和常量或宏一致:kEnumName 或是 ENUM_NAME。单独的枚举值应该优先采用常量的命名方式。

函数命名

常规函数

函数名的每个单词首字母大写,没有下划线:

1
2
AddTableEntry()
DeleteUrl()

取值和设值函数

取值和设值函数要与存取的变量名匹配. 这儿摘录一个类,num_entries_ 是该类的实例变量:

1
2
3
4
5
6
7
8
9
class MyClass {
public:
...
int get_num_entries() const { return num_entries_; }
void set_num_entries(int num_entries) { num_entries_ = num_entries; }

private:
int num_entries_;
};

其它非常短小的内联函数名也可以用小写字母,例如。如果你在循环中调用这样的函数甚至都不用缓存其返回值,小写命名就可以接受。

名字空间命名

名字空间用小写字母命名, 并基于项目名称和目录结构: 例如:google_awesome_project

格式

缩进

只使用空格,每次缩进 2 个空格。

函数声明与定义

函数参数,逻辑条件,初始化列表: 要么所有参数和函数名放在同一行,要么所有参数并排分行。

除函数定义的左大括号可以置于行首外,包括函数/类/结构体/枚举声明,各种语句的左大括号置于行尾,所有右大括号独立成行。

函数看上去像这样:

1
2
3
4
ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) {
DoSomething();
...
}

如果同一行文本太多, 放不下所有参数:

1
2
3
4
5
6
ReturnType ClassName::ReallyLongFunctionName(Type par_name1,
Type par_name2,
Type par_name3) {
DoSomething();
...
}

甚至连第一个参数都放不下:

1
2
3
4
5
6
7
ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
Type par_name1, // 4 space indent
Type par_name2,
Type par_name3) {
DoSomething(); // 2 space indent
...
}

注意以下几点:

  • 返回值总是和函数名在同一行;
  • 左圆括号总是和函数名在同一行;
  • 函数名和左圆括号间没有空格;
  • 圆括号与参数间没有空格;
  • 左大括号总在最后一个参数同一行的末尾处(可选);
  • 右大括号总是单独位于函数最后一行;
  • 右圆括号和左大括号间总是有一个空格;
  • 函数声明和实现处的所有形参名称必须保持一致;
  • 所有形参应尽可能对齐;
  • 缺省缩进为 2 个空格;
  • 换行后的参数保持 4 个空格的缩进。

指针和引用表达式

句点或箭头前后不要有空格。指针/地址操作符 (*, &) 之后不能有空格。

1
2
3
4
x = *p;
p = &x;
x = r.y;
x = r->y;

函数返回值

函数返回时不要使用圆括号:

1
return x;  // not return(x);

变量及数组初始化

= 还是 () 均可,统一就好。下面两种方式都是正确的:

1
2
3
4
int x = 3;
int x(3);
string name("Some Name");
string name = "Some Name";

不缩进的语句

名字空间

名字空间不要增加额外的缩进层次:

1
2
3
4
5
6
7
namespace {

void foo() { // Correct. No extra indentation within namespace.
...
}

} // namespace

预处理指令

预处理指令不要缩进,从行首开始。即使预处理指令位于缩进代码块中,指令也应从行首开始。

1
2
3
4
5
6
7
// Good - directives at beginning of line
if (lopsided_score) {
#if DISASTER_PENDING // Correct -- Starts at beginning of line
DropEverything();
#endif
BackToNormal();
}

goto 语句

用于 goto 语句的自定义标号应该顶头写不缩进,而不管标号下的语句缩进到第几层。

类格式

访问控制块的声明依次序是 public:protected:private:, 每次缩进 1 个空格。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyClass : public OtherClass {
public: // Note the 1 space indent!
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);
};

注意事项:

  • 所有基类名应在 80 列限制下尽量与子类名放在同一行。
  • 关键词 public:protected:private: 要缩进 1 个空格。
  • 除第一个关键词 (一般是 public) 外,其他关键词前要空一行。如果类比较小的话也可以不空。
  • 这些关键词后不要保留空行。
  • public 放在最前面,然后是 protected,最后是 private。

初始化列表

下面两种初始化列表方式都可以接受:

1
2
// When it all fits on one line:
MyClass::MyClass(int var) : some_var_(var), some_other_var_(var + 1) {

1
2
3
4
5
6
7
8
9
// When it requires multiple lines, indent 4 spaces, putting the colon on
// the first initializer line:
MyClass::MyClass(int var)
: some_var_(var), // 4 space indent
some_other_var_(var + 1) { // lined up
...
DoSomething();
...
}

深入阅读

  1. Google Style Guide - Google 开源项目风格指南(原版)。
  2. Google 开源项目风格指南 - Google Style Guide 的社区中文版。

Comments