附录C 关键字浅谈
在C++11标准中(C++11.2.12)总共定义了73个关键字(keyword)、2个“准”关键字(identifiers with special meaning)和11个操作符替代字(alternative representation)[1]。
虽然 C++标准中的关键字很多,但并不都是有用的,有些已经被废弃,有些因使用不当则会导致“代码坏味”,作者将谈谈自己在多年开发过程中对它们的一些认识,仅作一家之言。
1.废弃的关键字
register。它已经在C++11里被正式废弃,现在的C++代码中不应该再出现这个单词。
2.停用的关键字
export。C++98引入这个关键字,它在C++11中被停用但保留。
3.建议不使用的关键字
C++从C中继承了很多关键字,所以它也继承了C语言面向过程的一些缺点,有些关键字应当慎用或不用,这样可以很好地避免“反模式”,绕过一些容易令人困惑的陷阱。
goto。首当其冲的当然是 goto,它带来的流程混乱问题已经众所 周知,应当使用 break、continue、return 等关键字来控制程序流程, 让代码逻辑更清晰。
switch-case。多分支开关语句同样会导致代码难以理解,不利 于维护,在面向对象的语言里可以用状态模式来消除 switch-case 的使 用,也可以用if+return、map+function来替代switch-case语句。
else。滥用if-else和if-else的多重嵌套是与switch-case同样 令人厌恶的存在,它引入了多个逻辑条件,使程序的流程很混乱,而 且会导致遗漏逻辑判断的隐患。消灭else关键字需要有清晰的头脑, 仔细分析业务逻辑,设计代码结构,多数情况下可以在if语句里及时 用return来结束函数。
while/do。while{}和 do{}while 循环是旧时代的遗产,完全可 以用for 取代它们,而且在C++11 中,for 还支持基于范围的循环,更加安全。比较常用的无限循环while(1)也可以用更简洁的for (;;)代替。
new/delete。它们曾经的任务是取代malloc和free,但它们并没 有解决内存泄漏的根本问题,现在应该使用标准库里的智能指针和vector等容器。
4.建议积极使用的关键字
auto。C++11里的auto关键字能够自动推导表达式类型,为程序 员提供了以前只有编译器才拥有的能力,极大地简化了我们声明对象 时的工作,非常方便,因此应该尽量多用它。不过需要注意它的语 义,auto总是推导出“值”语义,有的时候需要使用“auto&”或“auto&&”的形式避免拷贝代价(如在 for 循环里)。
default。这个 default 不用于 switch 语句,而用于声明构造函数 或析构函数的默认实现,明确地写出它不仅可以告诉编译器也可以告 诉代码阅读者,这个类是一个“no trival”的类。
nullptr。它取代了容易引起歧义的NULL和0,是语法层面上真正的空指针,相当于其他语言里的None/Nil,使用它可以使代码获得更 强的安全性。
5.“准”关键字
所谓“准”关键字,其实并不是关键字,它们只是普通的单词,
但能够在特定的C++语境里产生语法效果,此外没有其他的特殊含义。目前 C++标准仅定义了两个“准”关键字:final 和 override,用于类继承体系的控制,可以很好地增强表达能力,建议使用。
final。用于标识类或成员函数,禁止子类继承或重载。
override。用于标识虚函数,明确地表示成员函数重载了父类的 同名函数,避免误覆盖(overload)。
希望读者能够在今后的实践中采纳本文的建议,书写出更优雅易 读、给人看而不是给机器人看的代码。
使用 if-else 来完成全流程覆盖,不如使用 if-return 来完成筛查。
override在继承虚函数的子类声明的引号最后处表明。
map + function 是通过重载的方式,实现了 if-else的逻辑选择替代方案。
if-return则是另一种思路,通过反向筛选的方式,把不合格的数据剔除。从而保证了数据的安全。
状态设计模式则是更加上一层,从具体的代码逻辑层次调升到了面对对象实现方式,它有更好的可扩展性(增加继承子类),更好的私密性(单独类内管理,彼此分割),更贴合低耦合、高内聚的方式。
- [[二十三种设计模式:状态模式]]
- [[状态设计模式:代码介绍]]
- [[map + function 实现替代if - else]]
- [[C++11 新特性:default]]