[C++] 编程实践之1: Google的C++代码风格1:头文件

commander-cpp:单头文件C++ CLI库的工业级实践 CLI(命令行接口)是C++系统工具开发的基础能力,其核心在于参数解析、帮助文档生成与类型安全校验。传统方案如getopt或boost::program_options常面临编译依赖重、文档与代码不同步、子命令管理复杂等工程痛点。commander-cpp以C++17现代特性为基石,通过单头文件实现零构建耦合,利用链式调用建模CLI语义层级,并在编译期完成帮助文本生成与类型反射,显著提升工业场景下的可维护性与确定性。它不仅简化了车载诊断、OTA升级等嵌入式CLI开发,更可作为跨协议(HTTP/gRPC/MQ 阅读详情

  作为使用最为广泛的语言之一,C++也出现在众多开源项目中。为了有效管理C++丰富的语法所带来的复杂性和提高可读性,Google公司专门制定了C++代码风格建议。为了便于自己养成良好的编程习惯,同时为国内同行提供便利,我将原文内容以及YuleFox等人的中文翻译做一个精简版的总结。

头文件

  通常而言,每个.cc(.cpp)文件应该对应一个.h头文件,但也有例外,例如包含main()函数的文件。本小节主要讨论关于头文件的一些代码风格规范。

Self-contained头文件

头文件应该能够自给自足(也就是可以作为第一个头文件被引入),以.h结尾。至于用来插入文本的文件,说到底它们并不是头文件,所以应该以.inc结尾。不允许分离出-inl.h头文件的做法。

  所有头文件要能够自给自足。换言之,用户和重构工具不需要为特别场合而包含额外的头文件。详言之,一个头文件要有define保护,统统包含它所需要的其它头文件(这意味着当用户使用某一个.h头文件时,它不再需要包含该头文件所依赖的所有其它非库头文件),也不要求定义任何特别的symbols。
  例外:一个文件并不是self-contained的,而是作为文本插入到代码某处。或者文件内容实际上是其它头文件的特定平台(platform-specific)扩展部分。这些文件就需要用.inc文件扩展名。
  如果.h文件声明了一个模板或者内联函数,同时也在该文件加以定义。凡是有用到这些的.cc文件,就得统统包含该头文件,否则程序可能会在构建中链接失败,不要把这些定义放到分裂的-inl.h文件里。
  例外:如果某函数模板为所有相关模板参数显式实例化,或者本身就是某类的一个私有成员,那么它就只能定义在实例化该模板的.cc文件里。

#define保护

所有头文件都应该用#define来防止头文件被多重包含,命名格式应当是:<PROJECT>_<PATH>_<FILE>_H_.

  为保证唯一性,头文件的命名应该基于所在项目源代码树的全路径,例如项目foo中的头文件foo/src/bar/baz.h的#define保护方式应该为:FOO_BAR_BAZ_H_。

前置声明

尽可能地避免使用前置声明。使用#include包含需要的头文件即可。

定义:

  • 所谓“前置声明”(forward declaration)是类、函数和模板的纯粹声明,没有伴随着其定义。

优点:

  • 前置声明可以节省编译时间,多余的#include会迫使编译器展开更多的文件,处理更多的输入。
  • 前置声明能够节省不必要的重新编译时间。#include使得代码因为头文件中无关的改动而被重新编译多次。

缺点:

  • 前置声明隐藏了依赖关系,头文件改动时,用户的代码会跳过必要的重新编译过程。
  • 前置声明可能会被库的后续更改所破坏。前置声明函数或者模板有时候会妨碍头文件开发者变动其API,例如扩大形参类型,加个自带默认参数的模板形参等等。
  • 前置声明来自命名空间std::的symbol时,其行为未定义。
  • 很难判断什么时候该用前置声明,什么时候该用#include。极端情况下,用前置声明代替#include甚至都会暗暗地改变代码的含义:如果#include被B和D的前置声明所代替,test()就会调用f(void*)。前置声明了不少来自头文件的symbol时,就会比单单一行的#include冗长。*仅仅为了能前置声明而重构代码(比如用指针成员代替对象成员)会使代码变得更慢更复杂。

结论:

  • 尽量避免前置声明那些定义在其它项目中的实体。
  • 函数:总是使用#include。
  • 类模板:优先使用#include。

内联函数

只有当函数只有10行甚至更少时才将其定义为内联函数。

定义:

  • 当函数被声明为内联函数之后,编译器会将其内联展开,而不是按通常的函数调用机制进行调用。

优点:

  • 只要内联的函数体比较小,内联该函数可以令目标代码更加高效。对于存取函数以及气他函数体比较短,性能关键的函数,鼓励使用内联。

缺点:

  • 滥用内联将导致程序变得更慢。内联可能使目标代码量或增或减,这取决于内联函数的大小。内联函数非常短小的存取函数通常会减少代码的大小,但内联一个相当大的函数将戏剧性地增加代码大小。现代处理器由于更好地李永乐指令缓存,小巧的代码往往执行更快。

结论:

  • 一个较为合理的经验准则是:不要内联超过10行的函数。谨慎对待析构函数,析构函数往往比其表面看起来要更长,因为有隐含的成员函数和基类析构函数被调用。
  • 另一个实用的经验准则:内联那些包含循环或者switch语句的函数常常是得不偿失的(除非在大多数情况下,这些循环或者switch语句从不被执行)。
  • 有些函数即使声明为内联也不一定会被编译器内联:比如虚函数和递归函数就不会被正常内联。通常递归函数不应该声明成内联函数。(递归调用堆栈的展开并不像循环那么简单,比如递归层数在编译时可能是未知的,大多数编译器都不支持内联递归函数)。

#include的路径及顺序

使用标准的头文件包含顺序可增强可读性,避免隐藏依赖:相关头文件,C库,C++库,其他库的.h,本项目内的.h。

  项目内头文件应该按照源代码目录树结构排列,避免使用UNIX特殊的快捷目录.(当前目录)或者..(上级目录)。
  例如dir/foo.cc的主要作用是实现或者测试dir2/foo2.h的功能,foo.cc中包含头文件的次序如下:
    1. dir2/foo2.h(优先位置)
    2. C系统文件
    3. C++系统文件
    4. 其他库的.h文件
    5. 本项目内.h文件
  这种优顺序保证当dir2/foo2.h遗漏某些必要的库时,dir/foo.cc或者dir/foo_test.cc的构建会立刻终止。因此这一条规则保证维护这些文件的人们首先看到构建终止的消息而不是维护其他包的人们。
  dir/foo.cc和dir2/foo2.h通常位于同一目录下,但也可以放在不同目录下面。
  按照字母顺序对头文件包含进行二次排序是个不错的注意。注意较老的代码可能不符合这条规则,要在方便的时候修正它们。
  您所依赖的symbols被哪些头文件所定义,您就应该包含哪些头文件,forward-declaration的情况除外。比如您要用bar.h中的某个symbol,哪怕您所包含的foo.h已经包含了bar.h,也照样得包含bar.h,除非foo.h有明确说明它会自动向您提供bar.h中的symbol。不过凡是.cc文件所对应的“相关头文件”已经包含的,就不用再重复包含进其.cc文件里面了,就像foo.cc只包含foo.h就够了,不用再管后者所包含的其它内容。
  例外:有时平台特定(system-specific)代码需要条件编译(conditional include),这些代码可以放到其它includes之后,当然平台特定代码也要足够简练并且独立,例如:

#include "foo/public/fooserver.h"

#inlucde "base/port.h"  //For LANG_CXX11

#ifdef LANG_CXX11
#include <initializer_list>
#endif  // LANG_CXX11

总结

  1. 避免多重包含是学编程的最基本要求。
  2. 前置声明是为了降低编译依赖,防止修改一个头文件引发多米诺效应。
  3. 内联函数的合理使用可提高代码执行效率。
  4. -inl.h可提高代码的可读性。
  5. 标准化函数参数顺序可以提高可读性和易维护性。
  6. 包含头文件的名称使用比较完整的项目路径看上去很清晰,有条理;包含的次序还可以减少隐藏依赖,使得每个头文件在“最需要编译”的地方编译。头文件都放在对应源文件的最前面,这一点足以保证内部错误的及时发现了。
  7. 类内部的函数一般会自动内联,所以某函数一旦不需要内联,其定义就不要再放在头文件里面了。
  8. 在#include中插入空行以分割相关头文件、C库、C++库,其它库的.h以及本项目内的.h是个好习惯。
C++:C++代码风格指南--Google(未完待续) 所谓「前置声明」(forward declaration)是类、函数和模板的纯粹声明,没伴随着其定义. 阅读详情

相关推荐

Google Cpp Guide

本文章主要记录内容讲解。未完成,还在持续更新…

KingOfMyHeart的博客 608

Effective C++笔记(二)

条款03:尽可能用const const的作用 (1)变量 常量,该变量不可被修改, 因此定义时必须被初始化 (2)指针 常量指针和指针常量 允许非const对象的地址赋给指向const对象的指针 因此可以简单的理解为,谁被const修饰,谁就不能改变。没有被修饰的不可轻易下结论。 #常量指针 const int a = 0; const int *p = &a; # p本身并不是常量,...

后而来者 299

C++经典算法(全代码版本)又名standard code library

全代码版本的c++经典算法含有各种类型的算法,比较全面,是很好的参考资料

C++之编程规范

google C++编码规范汇总

u010378559的博客 1349

RAG-Anything 实战:构建企业级多模态知识图谱问答系统

本文详细介绍了如何利用RAG-Anything构建企业级多模态知识图谱问答系统,解决跨模态文档处理的痛点。通过架构设计解析、部署实战指南和典型业务场景解决方案,帮助企业实现高效的知识管理和智能检索,提升决策效率。

weixin_29089057的博客 385

使用TMS320F28335控制四位共阳数码管

简要阐述利用F28335控制四位共阳数码管的整个过程,包括原理、思路、部分代码以及调试过程。

liujunhaozuishuai的博客 2658

C++编程规范(101条)读书随笔

1。组织和策略问题 如果人们按照程序员编程的方式修建房屋,那么一只啄木鸟就能毁灭整个文明。 第0条:不要拘泥于小节(又名:了解哪些东西不应该标准化) 不要规定缩进多少,应该规定要用缩进来体现代码的结构 不要强制行的具体长度,应该保证代码行的长度有利于阅读 不要在命名规范方面规定太多,应该规定的是使用一致的命名规范 不要规定注释体例(除非需要使用工具从特定的体例中提取文档),应该编写有用

beatbean 648

zynq+LWIP 裸机双网口实现(MIO+EMIO)+程序下载

芯片型号: ZYNQ: XC7Z010clg400开发软件:Vivado2022 + Xilinx Vitis 2022网卡芯片:RTL8211FDI(需要根据网口芯片型号修改对应的硬件配置代码。

thinking in 小宇宙 3405

谷歌C++编程规范

Google 经常会发布一些开源项目, 意味着会接受来自其他代码贡献者的代码. 但是如果代码贡献者的编程风格与 Google 的不一致, 会给代码阅读者和其他代码提交者造成不小的困扰. Google 因此发布了这份自己的编程风格指南, 使所有提交代码的人都能获知 Google 的编程风格.翻译初衷:我们翻译时也是尽力保持严谨, 但水平所限, bug 在所难免. 有任何意见或建议, 可与我们取得联系.中文版和英文版一样, 使用 开源许可.中文版修订历史:2008-07 1.0 : 出自 YuleFox 的

qq_41854911的博客 6198

操作系统期末大题类型题解

额,OS主要这回考程序分析题,PV操作、生产者消费者啊,哲学家进餐问题,死锁问题啊,如何避免死锁,经典银行家算法,页面置换算法啥的,磁盘调度......总计还有很多,就不一一说了 PV操作 谈到PV操作,首先要了解什么是信号量,其实就是用来解决互斥与同步问题的,分为原语wait(S)和signal(S),也就是我们常说的PV操作,在这里给出王道上的概念 wait(S){ while(S>0) S=S-1; } signal(S){ S=S+1; } 记录型信号量

ZXxxiaoxuan的博客 792

企业微信-审批控件中的外部选项的应用全流程完美解决方案

完美解决企业微信所有JS-SDK调用问题 完美解决苹果和PC端不适配的问题

qq_45195039的博客 5866

C++编程规范之23:头文件应该自给自足

摘要:     各司其责:应该确保所编写的每个头文件都能够独自进行编译,为此需要包含其内容所依赖的所有头文件。 如果一个文件包含某个头文件时,还要包含另一个头文件才能工作,就会增加交流障碍,给头文件的用户增添不必要的负担。     现在的C++编译器基本上都能够自动识别头文件保护符,甚至不会两次打开同一个头文件。有些编译器还提供了预编译的头文件,有助于确保不会经常分析那些常用而且很少变化的头

longshengguoji的专栏 3878

Unreal Engine鸿蒙移植实战:环境配置、构建流程与性能优化指南

游戏引擎移植是跨平台开发中的关键技术环节,其核心原理在于通过适配目标操作系统的底层接口和工具链,实现同一套代码在不同硬件和软件环境下的高效运行。这项技术的价值在于最大化代码复用率,降低多平台维护成本,并能让应用快速触达新兴生态系统的用户。在移动游戏和XR应用领域,随着鸿蒙HarmonyOS生态的快速发展,将成熟的商业引擎如Unreal Engine迁移至此平台,成为开发者探索新市场机会的重要路径。本文聚焦于Unreal Engine项目向鸿蒙系统的移植实践,详细解析了从环境搭建、源码适配到构建打包的全链路流

weixin_29011395的博客 405

C++ Google代码风格

C++ Google代码风格0 index(扉页)0.0 声明0.1 译者前言0.2 背景headers(头文件)1.1 Self-contained 头文件1.2. #define 保护1.3. 前置声明1.4. 内联函数1.5. #include 的路径及顺序译者(acgtyrant)笔记scoping(作用域)2. 作用域2.1. 命名空间2.2. 匿名命名空间和静态变量2.3. 非成员函数...

baidu_28926495的博客 1623

Qt基础之十九:进程与QProcess

进程就是一个程序的执行实例,也就是正在运行的程序。对操作系统来说,进程就是一个担当分配系统资源CPU时间、内存的实体。在Qt 中,我们使用QProcess来表示一个进程。这个类可以允许我们的应用程序启动一个新的外部程序,并且与这个程序进行通讯。当外部程序开始启动时,QProcess的状态为Starting;外部程序已经启动时,QProcess的状态为Running,并发送started()信号;当外部层序退出了,QProcess的状态为NotRunning(初始状态),并发送finished()信号。

草上爬的博客 1万+

物联网通信中NB-IoT、Cat.1、LTE-M该如何选择?

首先我们要确定我们产品的关键需求,例如:我们的设备是否对数据传输速率有较高的要求,有较高要求我们就需要选择较高传输速率的Cat.1来开发我们的产品。同时关于产品性能方面,我们对功耗、延迟、可靠性也会有所要求,例如我们的产品为移动端产品,不方便布线以及安装电源,那我们就会采用电池供电的方式,所以在选择时可以优先考虑低功耗产品,最终结合其他需求选择出合适的协议。首先,我们需求的产品是不同的,我们需要根据产品需求或项目需求来进行选择,NB-IoT、Cat.1、Cat.M都有属于自己的优势。

a1809032425的博客 1216

Google C++编程风格指南(一):头文件

 本指南的目的是通过详细阐述在C++编码时要怎样写、不要怎样写来规避其复杂性。本指南的另一个观点是C++特性的臃肿。C++是一门包含大量高级特性的巨型语言,某些情况下,我们会限制甚至禁止使用某些特性使代码简化,避免可能导致的各种问题 系列文章目录:Google C++编程风格指南(一):头文件        【本文】Google C++编程风格指南(二):作用域Google

周睿的博客(blog) 1623

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

BAML C++ SDK 代码风格指南:Google 布局与标准库命名的工程实践

本文以 [baml_language/sdks/cpp/STYLE.md](https://link.gitcode.com/i/51b97241bd9f795a24c743a694047dac) 为骨架,系统讲解 BAML C++ SDK 的代码风格约定:布局(Layout)采用 Google 风格,命名(Naming)遵循 C++ 标准库的下划线风格,以及这套约定背后的源码级实现与例外条款。读

gitblog_00688的博客 389

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C语言Google代码风格整理

想要写出整洁的代码就不得不遵循某种特定规范,在这篇文章中整理了C语言的Google代码规范。推荐刚刚接触代码的新手或是已经入门但是苦于代码编写风格的开发者阅读。

Reed_redd的博客 1197

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

google代码风格(C++)

from    http://code.google.com/p/google-styleguide/   版本:   3.133 原作者: Benjy Weinberger Craig Silverstein Gregory Eitzmann Mark Mentovai Tashana Landray 翻译: YuleFox yospaly 项目主页:

昨天的你 4010

Abseil代码风格指南:Google C++代码规范的实践

在现代软件开发中,代码风格一致性是保证项目可维护性和可读性的关键因素。Google的C++代码规范被业界广泛认可,而Abseil库正是这一规范的完美实践。作为Google内部C++代码库的开源版本,Abseil不仅提供了高质量的C++组件,更展示了如何在实际项目中应用Google的代码风格规范。 本文将深入解析Abseil代码库中的风格实践,帮助开发者理解和应用这些最佳实践。 ## 命名约定:...

gitblog_00685的博客 984

终极指南:掌握Google C++代码风格规范的10个核心技巧

Google C++代码风格规范是业界公认的C++编程标准,为开发者提供了一套完整的代码编写指南。作为C++程序员,遵循这套规范不仅能提升代码质量,还能让团队协作更加顺畅。本文将通过10个关键技巧,带你从规范到实践全面掌握Google C++代码风格。🚀 ## 📝 为什么需要代码风格规范? 在大型项目开发中,统一的代码风格至关重要。Google C++规范强调**可读性优先**、**一致性

gitblog_00338的博客 409

C++编程规范(参考Google、华为)

文件名及版权信息 1、文件名 C++文件名全部都是小写,且单词之间用_分割,如:verilog_parse.cpp 2、版权信息 所有文件均需要统一格式的版权信息。 头文件 1、在.h中使用#define来防止头文件被多重包含,并在最后注释出宏的名字 命名格式:<PROJECT>_<FILE>_H_ #ifndef TIMER_FLOW_H_ #define TIMER_FLOW_H_ ... #endif // TIMER_FLOW_H_ 2、尽量避免使用前置声明,优先使用#i

qq_39632811的博客 4878

Google C++编程规范 1 头文件

1. 头文件 通常每一个 .cc 文件都有一个对应的 .h 文件. 也有一些常见例外, 如单元测试代码和只包含 main() 函数的 .cc 文件. 正确使用头文件可令代码在可读性、文件大小和性能上大为改观. 下面的规则将引导你规避使用头文件时的各种陷阱. 1.1. #define 保护 所有头文件都应该使用 #define 防止头文件被多重包含, 命名格式当是: <PR...

aapx76947的博客 240

Google C++ Style Guide 谷歌 C++编码风格指南,深入理解华为与谷歌的编程规范——C和C++实践指南

来看,return;(比如刷新 log),您可以把它绑定到 _at_quick_exit(). 如果您想在 exit() 和 quick_exit() 都用上该 handler, 都。Tip: 使用 C++ 的类型转换, 如 static_cast<>(). 不要使用 int y = (int)x 或 int y = int(x) 等转换方式;TextQuery::TextQuery(std::string word) : word_(word) {} , 其中 word_ 自然是类内私有成员。

C++,Java,Python,C#编程选手,偶尔刷刷leetcode 1388

《GOOGLE C++ 编程规范》读书笔记

GOOGLE C++ 规范读书笔记 1、头文件 1、使用#define避免头文件被重复包含,定义的宏为全路径+文件名; 2、能使用前置声明的地方尽量不使用#include。即如果不需要访问类定义的情况下,使用类的前置声明即可;需要类定义时,则必须得包含头文件。 3、只有当函数只有10行甚至更少时才将其定义为内联函数;内联包含循环或switch语句的函数常常是得不尝失(除非在大多数情况下

pointersky的专栏 989
上一篇: [Leetcode] 82. Remove Duplicates from Sorted List II 解题报告
下一篇: [C++] 编程实践之1: Google的C++代码风格2:作用域
魔豆Magicbean
博客等级 码龄19年 146粉丝 742原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值