google c++代码规范-中文翻译

2023-11-20

头文件< Header Files>

The #define Guard

所有的头文件都应该使用#define等来防止头文件重复包含,宏的格式应该为:<PROJECT>_<PATH>_<FILE>_H_

#ifndef FOO_BAR_BAZ_H_

#define FOO_BAR_BAZ_H_

 

...

 

#endif // FOO_BAR_BAZ_H_

头文件依赖

当前面的声明已经满足依赖的时候,不要再使用#include

 

当你包含一个头文件的时候,你就引进了一种依赖,这种依赖会导致:一旦被包含的头文件发生改变,你的代码将会被重新编译。如果你的头文件还包含了其他的头文件,那么这些头文件的任何改变都会导致包含了你的头文件的代码被重新编译。因此,我们应该最小化包含头文件,特别要注意那些包含了其他头文件的头文件。

通过使用前向声明可以显著地减少需要包含的头文件的数量。例如,如果你的头文件想使用File类而不要进入声明了File类的文件,这时你的头文件就可以前向声明File类,而替代掉#include "file/base/file.h"

如何能在头文件中使用File类而不用进入它的定义文件?

l  我们可以声明Foo *或者Foo &类型的数据成员。

l  我们可以声明但并不定义带参和(或)返回Foo类型值得函数。(一个例外是,如果参数Foo或const Foo&拥有非显式的单参数构造,那么这种情况下就需要全面的定义以支持自动类型转换)。

l  我们可以定义Foo类型的静态数据成员。这是因为静态数据成员是被定义在类定义体之外的。

 

另一方面,如果你的类是Foo的子类或者有Foo类型的数据成员,那么你就必须包含Foo的头文件。

 

这样似乎我们应该使用指针(或者更好的是scoped_ptr,这是一个简单的智能指针,它能够保证在离开作用域后对象被自动释放)。但无论如何,这样做降低了代码的易读性和程序的运行效率,所以如果目的仅仅是减少头文件包含,那么还是应该避免这种方法的使用。

 

当然,.cc文件一般都需要它们所使用到的类的定义,并且通常它们都需要包含多个头文件。

 

注意:如果你在源文件中使用了Foo,那么无论是通过使用#include还是通过使用前向声明,你自己就应该引进Foo的定义。不要依赖于通过头文件传递而不是直接被包含的符号。例外的是,如果在myfile.cc中使用了Foo,那么可以替代在myfile.cc中,转而在myfile.h中进行包含(#include)或者前向声明Foo。

内联函数

只有当函数短小,并且少于或等于10行的时候才能定义它们为内联函数。

定义(Definition:

优点(Pros:

缺点(Cons:

结论(Decision:

 

The -inl.h Files

你也许会需要使用带有-inl.h后缀的文件名的文件来专门定义复杂的内联函数。

函数参数顺序规则

当定义一个函数的时候,其参数的顺序应该为:先是输入,然后是输出。

文件包含的命名和顺序规则

为了易读性和避免隐含依赖,请使用如下标准顺序:c 库,c++ 库,其他库的.h文件,你的工程的.h文件。

#include "base/logging.h"

#include"foo/public/fooserver.h"  //Preferred location.

 

#include <sys/types.h>

#include <unistd.h>

#include <hash_map>

#include <vector>

 

#include "base/basictypes.h"

#include"base/commandlineflags.h"

#include "foo/public/bar.h"

作用域(Scoping

 命名空间

鼓励在.cc文件中不使用命名空间。如果使用命名空间,则其名字最好是基于工程或者路径,而不要使用“using –顶层命名空间”(using-directive)。

Definition:

命名空间将全局域进行了细分,命名了不同的域,以便防止在全局域中发生名称冲突。

Pros:

命名空间提供了一种层次化命名方式,以替代类提供的另一种层次化的命名方式。

例如,如果两个不同的工程在全局域都有一个Foo的类,这就有可能在编译期或者运行期产生标志冲突。当两个工程在同一个命名空间内编码时,project1::Foo 和 project2::Foo就是不同的标志,这样就可以避免标志冲突。

Cons:

Decision:

不使用命名空间:

      允许并鼓励在.cc文件中不使用命名空间,以避免在运行期发生命名冲突。

·        namespace{                           // This is ina .cc file.

·         

·        //The content of a namespace is not indented

·        enum{ kUnused, kEOF, kError };       //Commonly used tokens.

·        boolAtEof() { return pos_ == kEOF; }  // Usesour namespace's EOF.

·         

·        }  // namespace

•    不要在.h等文件中不使用命名空间

使用命名空间

按照如下方式使用命名空间:

•    命名空间覆盖整个源代码文件,位于头文件包含、全局标志声明与定义、其他命名空间类的前向声明之后。

•    // In the .h file

•    namespace mynamespace {

•     

•    // All declarations are within thenamespace scope.

•    // Notice the lack of indentation.

•    class MyClass {

•     public:

•      ...

•      void Foo();

•    };

•     

•    }  //namespace mynamespace

 

•    // In the .cc file

•    namespace mynamespace {

•     

•    // Definition of functions is within scopeof the namespace.

•    void MyClass::Foo() {

•      ...

•    }

•    }  //namespace mynamespace

 

典型的.cc文件一般会有更多的复杂细节和对其他命名空间相关类的需求。

 

•    #include "a.h"

•     

•    DEFINE_bool(someflag, false, "dummyflag");

•     

•    class C; // Forward declaration of class C in the global namespace.

•    namespace a { class A; }  // Forward declaration of a::A.

•     

•    namespace b {

•     

•    ...code for b...         // Code goes against the left margin.

•     

•    }  //namespace b

 

•  不要在std命名空间内声明任何东西,更不要前向声明标准库类。在命名空间std中声明实体是未定义的行为,即这是不适宜的。声明来自标准库的实体,应包含相应的头文件。

•   你应该不使用“using –顶层命名空间”(using-directive),以避免使一个命名空间下的所有命名都有效。

 

•    //禁止 –这将破坏命名空间.

•    using namespace foo;

 

•   .cc文件和头文件的函数、方法及类中,你可以使用using-声明(using-declaration)。

•    // OK in .cc files.

•    // Must be in a function, method or classin .h files.

•    using ::foo::bar;

•   命名空间的别名允许使用在.cc文件的任何地方,和已经命名的覆盖整个.h文件及函数与方法的命名空间之内。

•    //简化在.cc文件中常用的命名

•    namespace fbz = ::foo::bar::baz;

•     

•    //简化在.h文件中常用的命名

•    namespace librarian {

•    // The following alias is available to allfiles including

•    // this header (in namespace librarian):

•    // alias names should therefore be chosenconsistently

•    // within a project.

•    namespace pd_s =::pipeline_diagnostics::sidetable;

•     

•    inline void my_inline_function() {

•      //namespace alias local to a function (or method).

•      namespace fbz = ::foo::bar::baz;

•      ...

•    }

•    }  //namespace librarian

注意头文件中的别名将会对所有包含该头文件的文件有效,所以那些公用头文件(独立在工程之外)和被它们所包含的头文件应该避免定义别名,以便保持API集尽量的小。

嵌套类(Nested Classes

作为接口的一部分,你可以考虑使用公用嵌套类,但应该仔细考虑命名空间,以在全局域中保持清晰的声明。

定义(Definition:)

嵌套类是指在一个类中定义另一个类,亦被称为成员类。

class Foo {

 

 private:

  //Bar is a member class, nested within Foo.

 class Bar {

   ...

  };

 

};

优点(Pros:

 

缺点(Cons):

 

结论(Decision:

除非嵌套类真的是接口的一部分,例如拥有一组方法选项的类,否则不要使它们成为公用的。

非成员函数,静态成员函数和全局函数(Nonmember, Static Member, and Global Functions

相对于全局函数,更应当使用命名空间内的非成员函数或者静态成员函数。纯粹使用全局函数的机会应当很少。

优点(Pros:

 

缺点(Cons:

 

结论(Decision:

定义没有绑定到类实例的函数有时是有用的,甚至是必须的,这样的函数可以是静态成员函数或则非成员函数。非成员函数应该不依赖于外部变量,并且尽量在同一个命名空间下。

如果一个类中只有一组静态成员函数,并且这些函数并不共享静态数据,那么应该使用命名空间来替代这个类。

与生产类定义在同一个编译单元内的函数,当其被其他的编译单元调用时,也许会产生一些不必要的耦合和连接时依赖。静态成员函数则特别能应对这种情况。可以考虑抽象出一个新类,或则在一个单独的库中的一个命名空间内编写函数。

如果你必须定义一个非成员函数,而它只是在它的.cc文件中被用到,可以使用一个没有名字的命名空间,或则静态链接以限制其作用域(例如,static int Foo() {...})。

局部变量(Local Variables

在最小的作用域内编写函数的变量,并且在声明时即初始化。

 

C++允许在函数体内的任何地方声明变量。我们则鼓励尽量在局部域声明它们,并且尽量靠近第一次使用它们的地方。这样就使读者更容易找到声明,知道变量是什么类型,和它是怎样被初始化的。尤其要用直接初始化代替声明和赋值。例如:

int i;

i = f();      // 坏 –-初始化从声明中独立出来了

 

int j = g();  // 好 –-声明与初始化在一起.

 

注意,在GCC编译器里,for (int i = 0; i < 10; ++i)内,i的作用域仅在循环体内,所以你可以在同一个域内的另一个循环体中使用i 。这在 if  和 while 内同样正确。例如:

while (const char* p = strchr(str, '/'))str = p + 1;

警告:如果变量是一个对象,每次它进入域被创建时,其构造函数将被调用,每次它离开域时,其析构函数将被调用。

// 效率低的实现:

for (int i = 0; i < 1000000; ++i) {

  Foof;  // 构造函数和析构函数被调用 1000000次。

 f.DoSomething(i);

}

将这样的变量声明在循环体外更具效率。

Foo f; // 构造函数和析构函数只被调用一次.

for (int i = 0; i < 1000000; ++i) {

 f.DoSomething(i);

}

静态和全局变量(Static and Global Variables

类(class)类型的静态和全局变量原本是被禁止的:由于构造和析构顺序的不确定性,它们将导致出现难寻的BUG。

 

诸如全局变量、静态变量、静态类成员变量和函数体内静态变量等拥有静态持续存储的对象,它们都必须是“普通旧数据”(Plain Old Data,简称POD)。属于POD只有整型、字符型、浮点型、指针型和普通旧数据(POD)的数组或结构体。

 

类的构造和静态变量的初始化的调用顺序在C++ 中只被部分的说明,甚至该顺序还会在每次的构建中发生改变,而这将导致难以发现的BUG。因此除了禁止全局的类类型,我们还不应该允许静态普通旧数据(POD)用函数的返回值来初始化,除非该函数(如getenv(),  getpid())本身并不依赖于任何全局量。

 

类似的,析构的调用顺序与构造的调用顺序刚好相反。既然构造顺序不确定,那么析构顺序也就不确定。例如,当程序结束时,一个静态变量已经被销毁了,但仍运行的代码(也许是另一个线程)试图访问它而失败。再如,静态字符串变量也许会在另一个包含了该字符串引用的变量之前优先销毁。

 

因此,我们仅允许使用包含POD数据的静态变量。这条规则完全不允许使用vector(使用C数组代替),和string(使用constchar []代替)。

 

如果你需要类类型的静态或全局变量,可以考虑在函数main()或者pthread_once()中初始化一个永远不会被释放的指针。注意这个指针必须是个原始指针,而不是智能指针,因为智能指针的析构正是我们所应该避免的析构顺序的问题。

 

类(Classes)

类是C++代码的基本单元,自然它也被广泛的使用着。这章列出主要规则,难道你在编写类时不去遵循它么?

在构造函数中应该做的工作(Doing Work in Constructors)

通常构造函数中应该尽量少的初始化成员变量。任何复杂的初始化都应该使用显式的Init()方法。

 

定义(Definition:

有关在构造体内如何初始化。

优点(Pros:

方便编码,而不用担心类是否被初始化。

缺点(Cons:

这样做在构造函数中可能出现的问题是:

l   

l   

l   

l   

结论(Decision:

如果你的对象需要重要的初始化,那么可以考虑显式的Init()的方法。特别是构造函数不应该调用虚函数、增加错误和访问可能没有初始化的全局变量等等。

默认构造函数(Default Constructors)

如果你的类中定义了成员变量而没有其他的构造函数,那么你就必须定义一个默认构造函数。否则编译器就会替你定义一个,而这并不好。

定义(Definition:

优点(Pros:

缺点(Cons:

结论(Decision:

如果你的类中定义了成员变量而没有其他的构造函数,那么你就必须定义一个默认构造函数(无参数的那个)。你应该使用这种一致而有效的方法初始化你的对象。

 

之所以这样就是因为如果你没有其他的构造函数而又不定义默认构造函数,那么编译器为你构建一个默认构造函数。而编译器构建的默认构造函数并不能智能的初始化你的对象。

 

如果你的类是从一个已经存在的类继承而来,而你并没有添加什么成员变量,那么你就不必定义默认构造函数了。

(ExplicitConstructors)



韩智柜    手机展柜

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

google c++代码规范-中文翻译 的相关文章

  • 多分类学习、多标签学习、多任务学习的区别

    Multi class Multi label Multi task 三者之间的区别与相同之处 1 直观解释 多分类学习 Multi class 一个分类器 但分的类别是包含多个的 例如 分类器判断苹果的颜色是 红色 黄色 青色 白色 这是
  • 移动端H5开发遇到的问题

    移动端开发必会出现的问题和解决方案 H5开发过程中难免会遇到一些兼容性等爬过坑的问题 移动端 H5 相关问题汇总 1px 问题 响应式布局 iOS 滑动不流畅 iOS 上拉边界下拉出现白色空白 页面件放大或缩小不确定性行为 click 点击
  • 让控制台输出彩色日志 windows

    经常看到一些开源软件 例如NDK编译的时候 操作系统启动的时候 打印的输出很多是彩色的 这样比较容易分辨哪些是重点 增强可读性 代码如下 cpp view plain copy include
  • 深度解析C++模版

    在C 发明阶段 C 之父Stroustrup和贝尔实验室的C 小组对原先的宏方法进行了修订 对其进行了简化并将它从预处理范围移入了编译器 这种新的代码替换装置被称为模板 而且它变现了完全不同的代码重用方法 模板对源代码重用 而不是通过继承和
  • Python的PIL库

    Python图像库PIL Python Image Library 是python的第三方图像处理库 图像类Image class Image类是PIL中的核心类 比如从文件中加载一张图像 处理其他形式的图像 或者是从头创造一张图像等 Im
  • Python代码实现发送163邮件(IMAP服务)

    1 注册163邮箱并登陆 https mail 163 com 2 开启 IMAP IMAP 服务 3 编写代码 进行发邮件操作 import smtplib from email mime text import MIMEText fro
  • 用MATLAB实现人脸识别

    1 人脸识别技术的细节 一般来说 人脸识别系统包括图像提取 人脸定位 图形预处理 以及人脸识别 身份确认或者身份查找 系统输入一般是一张或者一系列含有未确定身份的人脸图像 以及人脸数据库中的若干已知身份的人脸图像或者相应的编码 而其输出则是
  • 【C/C++】 - Linux下查找函数头文件 以及 man命令拓展

    背景 比如现在需要找C语言 sleep函数的头文件 使用man来查找 可以先man sleep 可以发现出来的默认是sleep 1 是一个User Commands 明显不是我们需要的 这里提示了 看sleep 3 那我们查看下sleep
  • VC++ MapWinGis篇(三)

    添加百度图层 BaiduMapProvider h pragma once include BaseProvider h include BaiduProjection h include
  • Open3D(C++)实现建筑物点云立面和平面分割提取

    Open3D C 实现建筑物点云立面和平面分割提取 近年来 点云技术在城市规划 机器人地图构建等领域得到广泛应用 本篇文章将介绍如何利用Open3D C 库实现建筑物点云立面和平面分割提取 准备工作 首先需要编译安装Open3D库 本文使用
  • 如何写接口测试用例

    一 接口测试用例基础知识 1 接口测试要测的是什么 接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互 测试的重点是要检查数据的交换 传递和控制管理过程 以及系统间的相互逻辑依赖关系等 2 接口测试的意义 按照分层测试模型
  • iOS App打包上架详细流程

    一 前言 作为一名iOS开发者 把辛辛苦苦开发出来的App上传到App Store是件必要的事 但是很多人还是不知道该怎么上传到App Store上 下面就来详细讲解一下具体流程步骤 二 准备 一个已付费的开发者账号 可分为 账号类型分为个
  • 在Qt Creator中实现Android设备调试

    在Qt Creator中实现Android设备调试 要在Qt Creator中调试和运行Android应用程序 需要先连接设备并设置Qt Creator以使用适当的工具链 本文将介绍如何在Qt Creator中连接Android设备并配置Q
  • STM32的FSMC地址线对应关系通俗易懂解读和和驱动TFT-LCD的原理

    STM32的FSMC地址线对应关系通俗易懂解读和和驱动TFT LCD的原理 当 Bank接的是 8 位宽度存储器的时候 HADDR 25 0 对应FSMC A 25 0 当 Bank接的是 16 位宽度存储器的时候 HADDR 25 1 对
  • 内聚、耦合

    一 耦合 内聚的了解 看懂就行 不用强背 那么什么是耦合 什么是内聚呢 我来做个解释 内聚性 又称块内联系 指模块的功能强度的度量 即一个模块内元素彼此之间结合的紧密程度的度量 若一个程序之间各元素之间 程序段之间 联系紧密 则内聚性就高
  • Maven--快照(SNAPSHOT)版本介绍

    Maven快照 SNAPSHOT 版本介绍 在 Maven 中 任何一个项目和构件都必须有自己的版本 版本的值可能是 1 0 0 1 0 alpha 4 1 3 SNAPSHOT 等 其中 1 0 0 1 0 alpha 4 是稳定的发布版
  • Python实现数值列表(数组)的逆置输出

    题目描述 输入10个数字 然后逆序输出 输入 十个整数 输出 逆序输出 空格分开 样例输入 1 2 3 4 5 6 7 8 9 0 样例输出 0 9 8 7 6 5 4 3 2 1 arr list map int input split
  • mgrid

    numpy中的一个函数叫mgrid 例子 import numpy as np X Y np mgrid 0 1 1 1 7 0 1 1 1 7 print X shape print X print Y shape print Y 生成两
  • 分配操作菜单

    目录 概述 介绍 数据库 后端 前端 效果展示 概述 在写后台管理系统时 我们可以根据不同的登录人 给予不同的功能菜单 如 给楼栋管理员登录时分配 楼栋管理 宿舍管理 所以在数据库就要创建 1 登录人与角色表 2再给角色表分配操作菜单 登录

随机推荐

  • va_start和va_end使用详解

    转载于 http www cnblogs com hanyonglu archive 2011 05 07 2039916 html 本文主要介绍va start和va end的使用及原理 在以前的一篇帖子Format MessageBox
  • 工作日记NO.13

    1 执行机安装Qt 2 编译精简Qt5 15 X库 3 研究liadwg项目 尝试编译
  • 元宇宙与数字孪生有区别

    在元宇宙爆红之前 有一项技术已经慢慢渗透到各行各业之中 它可以逼真 实时地还原现实世界 它就是 数字孪生 目前很多人认为元宇宙与数字孪生的区别不大 元宇宙是数字孪生在技术层面的进阶与优化 其实不然 元宇宙和数字孪生虽然都属于用数字技术构建虚
  • 【廖雪峰python入门笔记】字符串_转义字符的使用

    转义字符的使用 字符串可以用 或者 括起来表示 如果字符串本身包含 怎么办 比如我们要表示字符串 I m OK 这时 可以用 括起来表示 I m OK 类似的 如果字符串包含 我们就可以用 括起来表示 Learn Python in imo
  • Qt 教程(传智教育)

    1 一个简单的 Qt 应用程序 Qt一个类对应一个头文件 类名就是头文件名 QApplication 应用程序类 管理图形用户界面应用程序的控制流和主要设置 是 Qt 的整个后台管理的命脉 它包含主事件循环 在其中来自窗口系统和其它资源的所
  • 快速排序(三种算法实现和非递归实现)

    快速排序 Quick Sort 是对冒泡排序的一种改进 基本思想是选取一个记录作为枢轴 经过一趟排序 将整段序列分为两个部分 其中一部分的值都小于枢轴 另一部分都大于枢轴 然后继续对这两部分继续进行排序 从而使整个序列达到有序 递归实现 v
  • (转)原理到实现

    转 https mp weixin qq com s Mrr1Rnl 594Gyyn9fHekjw 1NFS介绍 NFS是Network File System的简写 即网络文件系统 NFS是FreeBSD支持的文件系统中的一种 NFS基于
  • opencv中resize错误可能导致的原因之一

    cv2 error OpenCV 4 5 5 1 error 5 Bad argument in function resize 在用resize时会产生这个错误 有可能时传入的图片不存在了 假如你是从摄像头读取的图片 需要通过 ret f
  • vue 子父组件间的那些事儿——搭建项目(一)

    一 搭建vue项目 1 环境准备 基于nodejs vue cli cnpm 搭建vue项目 由于本博主已经具备以上环境 现在直接进行项目搭建 环境准备可参考这篇博客 https blog csdn net xcymorningsun ar
  • uni-app使用CSS实现无限旋转动画

    本来想用uni createAnimation创建一个旋转动画 发现转完一圈后就不动了 没法循环旋转 后来又用setInterval每隔一个周期就把旋转角度加180度 发现运行一段时间后动画逐渐崩坏 应该是动画的周期和定时器的周期时间没有完
  • 为什么重写equals就要重写hashcode

    在学习java的时候常常提到 重写equals就要重写hashcode hashcode和equals是个绑定在一起的东西 要了解这个我们需要了解两个函数 hashCode 方法 散列码 hash code 是由对象导出的一个整型值 散列码
  • js 设置网页打印的页眉页脚和页边距

    http blog sina com cn s blog 629788b70100n9zr html
  • React 教程及其API接口文档

    React 详细中文开发文档 可以阅读 http reactjs cn react docs tutorial html 英文原文 http facebook github io react 中文论坛 http react china or
  • mmdetection No module named 'imagecorruptions'

    报错原因 imagecorruptions cpp文件需要重新编译 解决方案 mmdetection 目录下运行 python setup py develop
  • 权重计算方法_终身持续学习-可塑权重巩固(Elastic Weight Consolidation)

    回过头来梳理了一下EWC方法 在持续终身学习里面很经典的一个方法 Deepmind写的晦涩难懂x 当时折腾了好久才理解 因为自己有点菜 条件和目标 论文中 假设存在两个任务A和B 可以推广为旧任务和新任务 数据集分别为D和D 模型学习完任务
  • 2021-07-01 RuoYi-Vue-Plus

    提示 https gitee com JavaLionLi RuoYi Vue Plus from gitee search 疯狂的狮子li icon https www iconfont cn 渐变色 http color oulu me
  • ASP.NET 中实现 读取数据库二进制 下载

    实现思路 首先从数据库中把二进制 写入到服务器上 生成临时文件 然后再从服务器上 进行下载 具体代码如下 string filename test jpg 这个就是要存放到服务器的文件名 Response ContentType appli
  • Jenkins自动化测试

    学习 Jenkins 自动化测试的系列文章 Robot Framework 概念 Robot Framework 安装 Pycharm Robot Framework 环境搭建 Robot Framework 介绍 Jenkins 自动化测
  • mariadb主从复制

    1 准备两台服务器 一台设置为master服务器 一台设置为slave服务器 两台服务器先关闭防火墙 关闭selinux systemctl stop firewalld setenforce 0 两台服务器都需要安装mariadb 这里用
  • google c++代码规范-中文翻译

    头文件 lt Header Files gt The define Guard 所有的头文件都应该使用 define等来防止头文件重复包含 宏的格式应该为