zhngs

zhngs

c++注解(5)——工程管理和错误处理

一.工程管理
1.c++组织多文件
2.c++编译模型
3.依赖
4.测试
二.错误处理

一.工程管理

c++并没有现代语言专用的工程管理或者也可以说依赖管理的软件,如rust的cargo,javascript的npm。这和c++的历史包袱相关,我们应该正确认识这一点————c++在工程管理方面是不完美的,尤其是一些c++大型工程,编译是一个很头疼的问题,可能会有各种依赖缺失

1.c++组织多文件

c++从c继承了头文件的使用方式,这是一种很原始的多文件组织方式,也是c++为兼容c不得不做出的妥协

头文件的弊端:

  • 包含一个头文件,可能会瞬间包含上万行代码,导致编译速度很慢

  • 头文件没有包的概念,无法像现代语言一样只导出其中一部分代码

  • 头文件包含存在顺序,顺序不当可能会引起错误,甚至会出现循环引用的情况

我认为合适的做法:

  • 将头文件组织成单向无环图的依赖形式,类似go的依赖

  • 前置声明值得探讨,google编程规范旧版本倾向于使用前置声明,因为可以节省编译时间,但最新版又倾向于直接包含头文件,原因是前向声明如果需要改动的话,会存在潜在的安全问题

2.c++编译模型

c++从c继承了单遍编译的模型,实际上由于c++一些复杂的语法,c++是多遍编译,这也是编译速度慢的原因

对于c++的编译系统,可以使用makefile,linux内核的编译就是靠makefile文件,可供选择的还有cmake,是一个跨平台的构建系统,推荐使用,muduo也是用的cmake

3.依赖

c++无法通过软件来管理第三方包的依赖,只能通过手动下载,这是一个痛点,所以c++开发人员都喜欢造轮子

对于一些依赖,一般会有一个third_part的文件夹来存放第三方源码,通过源码编译来使用第三方库

4.测试

c++的单元测试推荐使用google test框架

二.错误处理

c++错误处理目前有两个:

  • 通过返回值,比如int或者bool

  • 通过抛异常

c++之父在他的论文里面详细论述了返回值和异常的用法,肯定了异常在编写标准库中的作用,但是在编写普通程序的时候,不推荐使用异常,还是应该使用返回值的方式,google编码规范同样也不提倡使用异常

现代的语言针对错误处理都做出了自己的努力,go可以返回多个值,非常常用的用法是其中一个值为err,rust拥有option和result,可以包裹两种不同的结果

c++17有一个optional,和rust的option差不多,可以了解一下

个人认为最佳实践:

  • 返回int值的形式的错误处理简单有效,推荐使用

  • 可以返回既可以携带值又可以表明出错的数据结构,如智能指针,默认初始化为空,vector默认初始化也为空