Google C++编程规范(一)

来源:互联网 发布:2016淘宝如何收藏店铺 编辑:程序博客网 时间:2024/06/06 19:01

转载于: 分享C++编程规范


前言

本文面向刚入门学习C++的童鞋,老鸟们可选择性绕路。

在学习新的一门语言时,首先要了解这门语言相关规范,给自己脑子里留下印象。在今后编码过程中不断的实践并加深印象,从而形成一种习惯。

为什么选择Google C++编程规范呢? 引用李开复先生曾对它的评价:“我认为这是地球上最好的一份C++编程规范,没有之一,建议广大国内外IT研究使用。”

那么接下来我们一起认识它吧!

头文件

实际项目中常应用到如下几点规则:

1
2
3
4
5
//例如工程名称为helloGoogle,头文件名称hello.h
//那么在hello.h文件会出现#define防止头文件被*多重包含*
#ifndef HELLOGOOGLE_HELLO_H_
#define HELLOGOOGLE_HELLO_H_
#endif //HELLOGOOGLE_HELLO_H_
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//包含文件的次序
//hello.h
#ifndef HELLOGOOGLE_HELLO_H_
#define HELLOGOOGLE_HELLO_H_
#include <sys/types.h> //c系统文件
#include <unistd.h>//c++系统文件
#include <vector> //其他库文件
#include "base/base.h"//本项目内头文件
#endif //HELLOGOOGLE_HELLO_H_
//--------------------------
//hello.cpp
#include "hello.h"//优先位置
#include <sys/util.h>//c/c++系统文件
#include <math> //其他库文件
#include "base/types.h" //本项目内头文件
1
2
//hello.h
//尽量减少.h文件中#include的数量
1
2
3
4
5
6
//函数参数顺序 输入参数在前,输出参数在后
//说明:打印hello字符串,需要多久时间
//参数:
//[IN] count输入打印次数
//[OUT] times 输出消耗时间,单位毫秒
void printHello(IN int count, OUT int *times);

内联函数不常使用,-inl.h也先滤过。

作用域

  1. namespace

    1) 不具名命名空间

    2) 具名命名空间

优点:两个不同项目的全局作用域都有一个类 CHello,这样在编译或运行时造成冲突。如 果每个项目将代码置于不同命名空间中,project1::CHello 和 project2::CHello 作为不同符号 自然不会冲突。

建议:合理使用命名空间。

下面例子是具名命名空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//hello.h
#ifndef HELLOGOOGLE_HELLO_H_
#define HELLOGOOGLE_HELLO_H_
#include <sys/types.h> //c系统文件
#include <unistd.h>//c++系统文件
#include <vector> //其他库文件
#include "base/base.h"//本项目内头文件
namespace hellogoogle{
class CHello{
public:
void printHello(IN int count, OUT int *times);
};//hello
}//hellogoogle
#endif //HELLOGOOGLE_HELLO_H_
1
2
3
4
5
6
//hello.cpp
namespace hellogoogle{
void CHello::printHello(IN int count, OUT int *times){
//...
}
}

嵌套类

​ 不常使用,不在这里阐述。

函数 :非成员函数 +静态成员函数+全局函数

​ 后期再开篇幅阐述。

变量:局部变量 + 全局变量

​ 后期再开篇幅阐述。

命名约定

​ 最重要的一致性规则是命名管理,命名风格直接可以直接确定命名实体是:类型、变量、函 数、常量、宏等等,无需查找实体声明,我们大脑中的模式匹配引擎依赖于这些命名规则。
命名规则具有一定随意性,但相比按个人喜好命名,一致性更重要,所以不管你怎么想,规 则总归是规则。

  1. 通用命名规则

    函数命名、变量命名、文件命名应具有描述性,不要过度缩写,类型和变量应该是名词,函 数名可以用“命令性”动词。达到顾名思义的效果。

    例子:

    1
    2
    3
    4
    5
    6
    7
    // Good
    int num_errors;
    int num_completed_connections;
    //Bad
    int n;
    int nerr;
    int n_comp_conns;
  2. 文件命名

    文件名要全部小写,可以包含下划线(_)或短线(-),按项目约定来。

    1
    2
    3
    my_useful_class.cc
    my-useful-class.cc
    myusefulclass.cc

    通常,尽量让文件名更加明确,http_server_logs.h 就比 logs.h 要好,定义类时文件名一 般成对出现,如 foo_bar.h 和 foo_bar.cc,对应类 FooBar。
    内联函数必须放在.h 文件中,如果内联函数比较短,就直接放在.h 中。如果代码比较长, 可以放到以-inl.h 结尾的文件中。对于包含大量内联代码的类,可以有三个文件:

    1
    2
    3
    url_table.h // The class declaration.
    url_table.cc // The class definition.
    url_table-inl.h // Inline functions that include lots of code.

  3. 类型命名

    类型命名每个单词以大写字母开头,不包含下划线:MyExcitingClass、MyExcitingEnum。
    所有类型命名——类、结构体、类型定义(typedef)、枚举——使用相同约定,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    // classes and structs
    class UrlTable { ...
    class UrlTableTester { ...
    struct UrlTableProperties { ...
    // typedefs
    typedef hash_map<UrlTableProperties *, string> PropertiesMap;
    // enums
    enum UrlTableErrors { ...

  4. 变量命名

    变量名一律小写,单词间以下划线相连,类的成员变量以下划线结尾,如 my_exciting_local_variable、my_exciting_membervariable

    普通变量命名:

    1
    2
    3
    string table_name; // OK - uses underscore.
    string tablename; // OK - all lowercase.
    string tableName; // Bad - mixed case

    类数据成员:

    1
    2
    3
    4
    class UrlTableTester {
    string name_;
    int num_entries_;
    }

    结构体的数据成员可以和普通变量一样,不用像类那样接下划线:

    1
    2
    3
    4
    struct UrlTableProperties {
    string name;
    int num_entries;
    }

  5. 常量命名

    在名称前加 k:kDaysInAWeek。

    所有编译时常量(无论是局部的、全局的还是类中的)和其他变量保持些许区别,k 后接大 写字母开头的单词:

    1
    const int kDaysInAWeek = 7;

  6. 函数命名

    普通函数大小写混合, 存取函数则要求与变量名匹配:

    1
    2
    3
    4
    MyExcitingFunction()
    MyExcitingMethod()
    my_exciting_member_variable()
    set_my_exciting_member_variable()。

    普通函数:
    函数名以大写字母开头,每个单词首字母大写,没有下划线:

    1
    2
    AddTableEntry()
    DeleteUrl()

    存取函数:
    存取函数要与存取的变量名匹配,这儿摘录一个拥有实例变量 numentries的类:

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

  7. 枚举命名

    枚举值应全部大写,单词间以下划线相连:MY_EXCITING_ENUM_VALUE。
    枚举名称属于类型,因此大小写混合:UrlTableErrors。

    1
    2
    3
    4
    5
    enum UrlTableErrors {
    OK = 0,
    ERROR_OUT_OF_MEMORY,
    ERROR_MALFORMED_INPUT,
    };

  8. 宏命名

    你并不打算使用宏,对吧?如果使用,像这样:MY_MACRO_THAT_SCARES_SMALL_CHILDREN。
    通常是不使用宏的,如果绝对要用,其命名像枚举命名一样全部大写 、 使用下划线:

    1
    2
    3
    #define ROUND(x) ...
    #define PI_ROUNDED 3.0
    #define MY_EXCITING_ENUM_VALUE 1

  9. 其他

    当命名与现有 C/C++实体相似的对象时,可参考现有命名约定:

    1
    2
    3
    4
    5
    bigopen() //函数名,参考 open()
    uint //typedef 类型定义
    bigpos //struct 或 class,参考 pos
    sparse_hash_map //STL 相似实体;参考 STL 命名约定
    LONGLONG_MAX //常量,类似 INT_MAX
  10. 总结

    10.1 总体规则:不要随意缩写,如果说ChangeLocalValue ChangeLocalValue ChangeLocalValue ChangeLocalValue写作 ChgLocVal ChgLocVal ChgLocVal ChgLocVal还有情可 原的话,把ModifyPlayerName ModifyPlayerName ModifyPlayerName ModifyPlayerName写作 MdfPlyNm MdfPlyNm MdfPlyNm MdfPlyNm就太过分了,除函数名可适当为动 词外,其他命名尽量使用清晰易懂的名词;

    10.2 宏、枚举等使用全部大写+ + + +下划线;

    10.3 变量(含类、结构体成员变量)、文件、命名空间、存取函数等使用全部小写+ + + +下划线 , 类成员变量以下划线结尾,全局变量以g g g g开头;

    10.4 普通函数、类型(含类与结构体、枚举类型)、常量等使用大小写混合,不含下划线;

    10.5 参考现有或相近命名约定。

帮助

我会陆续更新C++相关文章,可以关注我的微博。

原创粉丝点击