命名应该含义明确,不要为了节省空间使用缩写。
int n; // Bad - 无明确含义的单字母名称
string cstmrName; // Bad - 非约定俗成的缩写
int width, height; // OK - 含义明确
int numColors; // OK - num属于约定俗成的缩写
for (int i = 0; i < 100; ++i) // OK - 循环变量可以使用单个字母的命名
template <class T> // OK - T用做模板参数属于约定俗成的写法
首字母缩写词只在需要时大写第一个字母。
class URLTable // Bad
class UrlTable // OK
string XMLFileName; // Bad
string xmlFileName; // OK
文件名全部为小写,单词之间没有其它符号。头文件以.h为扩展名,实现文件以.cpp为扩展名。一般情况下,一个类对应一个.h文件和一个.cpp文件,文件名与类的名字相同。
所有类型,包括类、结构体、枚举(包括枚举项)、和类型定义(typedef)等,遵循相同的命名方式:每个单词的第一个字母大写。类型名一般为名词。
class FooBar
{
...
};
struct BarBaz
{
...
};
enum ColorChannel
{
RedChannel = 0,
GreenChannel = 1,
BlueChannel = 2,
};
typedef hash_map PropertiesMap;
using PropertiesMap = hash_map;
在对枚举项命名时,为了避免歧义,枚举项名称中应至少包含枚举类型名称中的一个单词。
enum CaseSensitivity
{
Insensitive,
Sensitive,
}; // Bad
enum CaseSensitivity
{
CaseInsensitive,
CaseSensitive,
}; // Good
变量名(包括函数的参数),第一个字母小写,后面每个单词的第一个字母大写。不要使用匈牙利命名法(变量名前加表示类型的前缀)。
int iNumImages; // Bad
int numImages; // OK
string strTableName; // Bad
string tableName; // OK
类的成员变量加m_前缀,结构体的成员变量则不加任何前缀。全局变量加g_前缀。静态成员变量不加前缀。
class UrlTableProperties
{
string m_name;
int m_numEntries;
};
struct ImageInfo
{
int width;
int height;
...
};
vector、list、map等容器类型的变量,使用名词的复数形式表示。
vector holidays;
map employeeRoles;
QVector images;
函数的第一个字母小写,后面每个单词的第一个字母大写。Qt中的slot采用和函数一样的命名方式。
// 常见的函数命名方式
add() // 动词
addTableEntry() // 动词+名词
setColor() // set+名词
hasFocus() // has+名词
canConvert() // can+动词
canChangeProperty() // can+动词+名词
toBase64() // to+名词
isArray() // is+名词
isEmpty() // is+形容词
isChecked() // is+形容词
isMovingEnabled() // is+形容词
color() // 名词前面的get可以省略
autoCompletion() // 名词前面的is可以省略
常量采用和变量相同的命名方式。
const int daysInAWeek = 7;
宏定义用大写字母表示,单词之间用下划线分割。
#define ROUND(x) ...
#define PI_ROUNDED 3.0
名称空间采用和类型相同的命名,即每个单词的第一个字母大写。
namespace FooBar
{
...
};
花括号应独占一行,除非花括号用来表示可用一行代码表示的inline的函数体,或表示初始化列表。
class Foo
{
public:
Foo();
~Foo() {}
private:
struct Bar
{
...
};
};
int FooBar()
{
...
}
for (int i = 0; i < 10; ++i)
{
...
}
int array[] = {1, 2, 3, 4};
必须有一个空格的位置:
- 二元操作符,包括赋值符号的两侧
- 关键字和圆括号之间
- 不在行末的逗号和分号后
- 表示继承和初始化列表的冒号两侧
- 只有一行语句的函数体的花括号与语句之间
- delete和[]之间,以及[]和变量名之间
不能有空格的位置:
- 逗号和分号前
- 圆括号和尖括号内侧
- 函数名和圆括号之间
- 一元操作符和操作数之间
- 空的圆括号和花括号中
- 表示初始化列表的花括号和值之间
- 范围操作符(::)两侧
- #号右侧
class Foo : public Bar
{
public:
Foo(int b) : Bar(), m_baz(b) {}
void reset() { m_baz = 0; }
private:
int m_baz;
}
for (int i = 0; i < 5; ++i)
{
...
}
x = 0;
x = -5;
++x;
if (x && !y)
{
...
}
delete [] buffer;
表示指针和引用的符号和&和类型之间加一个空格,但和&与变量名之间不加空格。
char *fileName;
const QString &fileName;
可以使用空行将代码分组,但不要使用超过一个空行。
所有头文件都要使用#ifndef #define #endif防止头文件被多重包含。不要使用#pragma once。
#ifndef FOO_BAR_H
#define FOO_BAR_H
...
#endif // FOO_BAR_H
头文件本身应包含所有需要的头文件,以便在引用它时不需要首先包含其它的头文件。在头文件中,按照下面的顺序包含需要的头文件:C标准库,C++标准库,其它库的头文件,项目内的其它头文件。在引用头文件的.cpp文件中,总是把它对应的头文件放在其它所有头文件的前面。同种类型的头文件按照字母表的顺序决定哪个放在前面。避免包含不必要的头文件。
// foo.cpp文件
#include "foo.h" // foo.cpp related header
#include // C library
#include // C library
#include // C++ library
#include // C++ library
#include // Qt library
#include "bar.h" // other header files in your project
注释符号可以使用//,也可以使用/**/。注释符号和注释内容之间有一个空格。注释在一行的末尾时,注释符号和代码之间要有一个空格。