【编码】关键字之戒

每次写C函数时,我一般会在其函数名前加上extern, 或许有人抱有疑问了:C函数本来不就默认处于全局作用域的吗?加不加extern都一样。不过如果要限于文件作用域内,倒是该加上staticextern前缀。如果规则这么简单倒还好,但由于 C/C++ 糟糕的编译模型,我们不得不处理另一种问题:如何声明一个全局函数?其实规则应该类似:直接声明一个函数,或在函数的声明加上extern前缀,不定义函数体

然而这意味着代码复杂度两两相乘,即可以有四种情况:

  1. 函数定义没有extern, 函数声明没有extern.

  2. 函数定义有extern, 函数声明没有extern.

  3. 函数定义没有extern, 函数声明有extern.

  4. 函数定义有extern, 函数声明有extern.

更何况,您如何确定某文件是不是只有某函数的声明,即函数定义在别的文件。可万一该文件后文还有函数定义呢?再来个static其实要解决该问题好办,一开始就只记住externstatic关键字,且它们分别对应于全局作用域函数和文件作用域函数。若用全局作用域函数,文件要么有 extern 定义,要么有 extern 声明,且有只有一个文件包含 extern 定义,其他文件只能可以有一个 extern 声明;若用文件作用域函数,则在一个文件写 static 定义即可。禁止用没有 extern 或 static 关键字的函数,为了减轻记忆负担,关键字多多益善。可是,C新手一开始接触到的函数往往是不加extern的,如果入门书写的不好,比如依次教「声明与定义」,static. 那新手就很容易被弄得晕头转向,尤其入门书没有教好编译模型的话。事实上 K&R 之所以不适合入门,原因之一就是这个,我记得它没教编译模型,我后来读 Unix 编程环境时,花了好大费劲才弄懂这些。

其实上文关系到了 C/C++ 一个重大的特征之一:您有时不得通过种种关键字,来保证程序行为预期。此外,善用关键字,可以大大提高可读性。

我给这现象起了名,就叫「关键字之戒」,所有合格的 C/C++ 开发者都绕不过这严苛的戒律修行。掐指一算,我举一些对应的编程规范吧,若无特别说明,一般针对 C++::

  1. 若无意修改函数的引用形参,加const, 比如复制构造的参数。否则就传普通(引用)形参,比如

  2. 若某类函数不修改数据成员,其函数名后缀加const.

  3. 定义常量时,别用宏,用constexpr.

  4. 别让编译器隐式地定义拷贝构造的某函数,自己声明且加defaultdelete.

  5. 声明接收一个形参的构造函数时,加explicit, 以免意外的隐式转换构造。

  6. 用 class 时,别省略publicprivate, 哪怕您知道它默认用private.

  7. 如果某类会被继承,其析构函数声明为virtual.

  8. 若某 C 函数不接收任何形参,显式用void关键字,毕竟空形参则意味着形参不定。

  9. 如果不打算继承类,类名后加final.

不过话说回来,关键字之戒可能恰恰反映了 C/C++ 作为系统编程语言,对底层程序入木三分的控制吧,与复杂度一样名副其实的细度。当然,新一代的系统编程语言应该可以通过更好的语法设计,大破弃键字之戒。比如 C++ 相对于 C, 废除了空形参意味着形参不确定的特性,引入了代替externstatic的命名空间,C++17 更有传说中的模块编译模型。Rust 可能更青出于蓝。

本文转自 一点资讯

微信号:IdeaofSE

来源:软件工程之思,本文观点不代表自营销立场,网址:https://www.zyxiao.com/p/100592

发表评论

电子邮件地址不会被公开。 必填项已用*标注

侵权联系
分享本页
返回顶部