Google C++编程风格指南

0. 背景


  每一个C++程序员都知道,C++具有很多强大的语言特性,但这种强大不可避免的导致它的复杂,这种复杂会使得代码更易于出现bug、难于阅读和维护。

  本指南的目的是通过详细阐述在C++编码时要怎样写、不要怎样写来规避其复杂性。这些规则可在允许代码有效使用C++语言特性的同时使其易于管理。

1. 头文件


1.1 #define保护

  • 目的:防止头文件被多重包含
  • 原型:
#ifndef  XXX_XXX_H
#define XXX_XXX_H
...
#endif //XXX_XXX_H

1.2 能依赖声明的就不要依赖定义

  使用前置声明,尽量少.h文件中#include的数量,防止依赖

1.3 内联函数

  • 只有当函数少于10行甚至更少时,才定义为内联函数
  • 函数声明为内联,编译器直接在调用处展开代码,节省成本
  • 析构函数不应该内联,析构函数往往比其表面看起来要长
  • 不要内联那些包含循环、switch语句的函数
    • 除非大多数情况下,循环和switch从不执行
  • 虚函数和递归函数即使被声明为内联函数,实际上他不一定被执行

1.4 函数参数顺序

  • 输入参数在前,输出参数在后
  • 输入参数一般为:值 或 常数引用
  • 输出参数一般为: 非常数指针
  • 好处:
    • 提高可读性和易维护性
    • 对函数参数的堆栈空间有轻微影响

1.5 包含文件的次序

  C库 > C++库 > 其他库的h > 项目内的h

2. 作用域


2.1 命名空间

2.1.1 定义

  • 将全局作用域分为不同的、具名的作用域
  • 防止全局作用域命名冲突

2.1.2 优点

  • 提供了可嵌套的命名轴线
  • 命名轴线功能距离
    • project1 : : Foo
    • project2 : : Foo

2.1.3 缺点

  在头文件中使用不具名的空间容易违背C++的唯一定义原则

2.1.4 结论:根据上下文合理使用命名空间

  • .cc文件允许甚至提倡不具名命名空间

    • .cc文件包含更多、更复杂的细节
    • 有对其他命名空间中类的引用
  • .h不要使用不具名命名空间

2.2 嵌套类

  • 不要把嵌套类定义为public,除非他们是接口的一部分
  • 最好将嵌套类的声明置于命名空间中

2.3 非成员函数 / 静态成员函数 / 全局函数

  • 使用命名空间中的非成员函数/静态成员函数
  • 尽量不使用全局函数
  • 更好的方法是:将非、静作为新类的成员
  • 如果单纯为了封装,将不相干的函数放在一起,那还是用命名空间

2.4 局部变量

  • 尽可能置于最小作用域,最好声明变量时就初始化
  • 声明与第一次使用位置越近越好
  • for(int i = 0; i < 10; ++i)
    • gcc可正确执行,其他for循环重用第一次循环定义的i

2.5 全局变量

  • class类型全局变量是被禁止的
  • 内置类型的全局变量是允许的,但使用要三思
  • 多线程代码中非常数全局变量也是被禁止的

3. C++类


3.1 构造函数的职责

  • 职责:只进行没有实际意义的初始化
  • 有意义的数据用init方法实现
  • 缺点:
    • 不易捕获错误,不能使用异常
    • 操作失败会造成对象初始化失败,引起不确定状态
  • 对单参数的构造函数使用C++关键字explicit
    • 单参数构造函数必须是明确的
    • 拷贝构造函数大多数情况也要声明explicit

      例外:特意作为其它类的透明包装器的类
    • 禁止使用拷贝构造函数和赋值操作的宏

3.2 结构体和类

  仅当只有数据时使用struct,其他一概使用class

3.3 继承

  • 使用组合通常比使用继承更适宜
  • 如果使用继承,只使用公共继承
  • 所有继承必须是public,想私有继承的话,应采取包含基类实例的方式替代
  • 如果该类有虚函数,其析构函数也应该为虚函数
  • 派生类重定义基类的虚函数时,该派生类函数夜莺声明为virtual函数

3.4 多重继承

  • 应用场景:

      只有至多一个基类中含有实现,其他基类都是纯接口类
  • 优点:

      相比单继承,可复用更多代码

3.5 接口

  • 需满足的条件:

    • 只有纯虚函数和静态函数
    • 没有非静态成员函数
    • 没有定义任何构造函数
  • 必须为之声明虚析构函数
    • 确保接口的所有实现可被正确销毁
    • 此时,该虚析构函数亦为纯虚函数

3.6 操作符重载

  一般情况下不要重载操作符

3.7 存取控制

  • 即get/set函数
  • 存取函数一般内联在头文件中

3.8 Summary

  • 不在构造函数中做太多与逻辑相关的初始化
  • 编译器默认提供的构造函数不会对变量进行初始化
  • 子类重载的虚函数也要声明virtual关键字

4. 智能指针和其他C++特性


  • 智能指针安全第一,方便第二,尽可能局部化

    • 一般用scoped_ptr
    • 任何情况下不用auto_ptr
    • 对stl容器对象,使用shared_ptr
  • 引用形参加上const,否则使用指针形参
    • 避免丑代码:(*ptr)++
    • 对于拷贝构造函数,const是必须的
  • 函数重载的使用要清晰/易读
  • 少用缺省函数参数
  • 禁止使用变长数组和alloca
  • 合理使用友元
  • 慎用异常
  • 使用C++风格的类型转换,除单元测试外不要使用dynamic_cast
  • 能用前置自增/减,不用后置自增/减
    • 前置自增效率更高,后置自增自减要对变量值i进行依次拷贝
    • 如果i是迭代器或者其他非数值类型,一定要用前置
  • const能用则用,提倡const在前
    • const变量/函数/参数,会为编译时类型检测增加了一层保障
  • 尽量避免使用宏(c++中)
    • 尽量以内联函数、枚举、常量代替之
    • 不要在头文件中定义宏
  • 整数用0,实数0.0,指正NULL,字符串‘\0’
  • 推荐用sizeof(varname)代替sizeof(type)
  • 只使用Boost中被认可的库

5. 命名约定

  • 不要随意缩写,除非常用约定俗成的缩写
  • 函数名可适当为动词,其他命名使用名词
  • 全部大写+下划线: 宏/枚举
  • 全小写+下划线: 变量(含类变量/结构体变量)、文件、命名空间、存取函数
  • 大小写混合: 函数/类型(类/结构体/枚举)/常量

6.思维导图笔记



大图

读书笔记 |Google C++编程风格指南的更多相关文章

  1. Java学习笔记(四)——google java编程风格指南(上)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

  2. Java学习笔记(五)——google java编程风格指南(中)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

  3. Java学习笔记(六)——google java编程风格指南(下)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

  4. Google C++编程风格指南 - 中文版

    Google C++编程风格指南 - 中文版 from http://code.google.com/p/google-styleguide/ 版本: 3.133原作者: Benjy Weinberg ...

  5. google C++编程风格指南之头文件的包括顺序

    google C++编程风格对头文件的包括顺序作出例如以下指示: (1)为了加强可读性和避免隐含依赖,应使用以下的顺序:C标准库.C++标准库.其他库的头文件.你自己project的头文件.只是这里最 ...

  6. Google Java编程风格指南

    出处:http://hawstein.com/posts/google-java-style.html 声明:本文采用以下协议进行授权: 自由转载-非商用-非衍生-保持署名|Creative Comm ...

  7. Google Java编程风格指南中文版

    作者:Hawstein出处:http://hawstein.com/posts/google-java-style.html声明:本文采用以下协议进行授权: 自由转载-非商用-非衍生-保持署名|Cre ...

  8. Google C++编程风格指南

    作者:Hawstein 出处:http://hawstein.com/posts/google-cpp-style-guide.html 前言 越来越发现一致的编程风格的重要性,于是把Google的C ...

  9. Google Java 编程风格指南 —— 见微知著

    目录 前言 源文件基础 源文件结构 格式 命名约定 编程实践 Javadoc 后记 前言 这份文档是Google Java编程风格规范的完整定义.当且仅当一个Java源文件符合此文档中的规则, 我们才 ...

随机推荐

  1. java 动态代理学习(Proxy,InvocationHandler)

    前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里 ...

  2. SQL Server 中的嵌套事务与@@TranCount(转)

    在处理事务的时候,一般都用RollBack Transaction来回滚,但是如果在嵌套事务中这样使用的话,就会出现错误. 在SqlServer里,嵌套事务的层次是由@@TranCount全局变量反映 ...

  3. sublime每次打开时都提示升级,怎么取消这个弹出框?

    答案其实很简单,设置如下: 进入Preferences -> Settings-User ,添加 "update_check": false 重启Sublime. 发现了什么 ...

  4. ZKW费用流修正

    #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #inc ...

  5. Apache HTTP Server mod_session_dbd 远程安全漏洞(CVE-2013-2249)

    漏洞版本: Apache 2.4.2 漏洞描述: BUGTRAQ ID: 61379 CVE(CAN) ID: CVE-2013-2249 Apache HTTP Server是开源HTTP服务器. ...

  6. 基于物联网操作系统HelloX的智慧家庭体系架构

    基于物联网操作系统HelloX的智慧家庭体系架构 智慧家庭是物联网的一个分支应用,是一个被广泛认同的巨大IT市场空间.目前市场上已经有很多针对智慧家庭的产品或解决方案,但与移动互联网不同,智慧家庭至今 ...

  7. 金牌分析师助力 鲁泰A图谋再造一个“鲁泰”?_财经_中国网

    金牌分析师助力 鲁泰A图谋再造一个"鲁泰"?_财经_中国网 金牌分析师助力 鲁泰A图谋再造一个"鲁泰"?

  8. Android程序的入口点和全局变量设置--application

    首先看看 application的官方文档 我之前一直以为Android程序的入口点就是带MAIN和LAUNCHER的Activity的onCreate方法,看来我是错了~  原来真正的入口点是 Ap ...

  9. 细说Lucene源码(一):索引文件锁机制

    大家都知道,在多线程或多进程的环境中,对统一资源的访问需要特别小心,特别是在写资源时,如果不加锁,将会导致很多严重的后果,Lucene的索引也是如此,lucene对索引的读写分为IndexReader ...

  10. YYCache 源码分析(一)

    iOS 开发中总会用到各种缓存,YYCache或许是你最好的选择.性能上有优势,用法也很简单.作者ibireme曾经对比过同类轮子:http://blog.ibireme.com/2015/10/26 ...