C++编码风格与规范

命名约定

一般命名原则

命名应该含义明确,不要为了节省空间使用缩写。

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

注释

注释符号可以使用//,也可以使用/**/。注释符号和注释内容之间有一个空格。注释在一行的末尾时,注释符号和代码之间要有一个空格。

你可能感兴趣的:(C++)