下面写的文章是要介绍从一个较高的层次去把握C++中的复杂性。其中最重要的一个指导思想就是在学习的过程中注意你正学习的技术或细节到底是80%场景下的还是20%场景。
因此,当你发现在这个习以为常的环境下居然出现了新的可能性时,你当然是会欢呼雀跃的(比如我当年读《Modern C++ Design》的时候就有一次从早读到晚,午饭都没吃),然而实际上呢?
其它语言中也许早就有first-class的支持了,其它语言也许根本不需要这个惯用法,因为它们就没有这些缺陷。此外,从实践的角度来说,更重要的是,这些“解决方案”也许你平时编程根本就用不到。
不,我当然不是说这些补丁方案不重要。正如前面所说,C++中繁杂的技巧并非空穴来风,总有实际问题在背后驱动的。但问题是,对于我们日常编程来说,这些“实际问题”简直是八杆子打不着的。犯不着先费上80%的劲儿把20%时候才用到的东西揣在脑子里,用的时候查文档或书就行了。
看到这里,塑造C++中特定的心态哲学的另一个原因想必你也已经知道了。实际上,这个原因才是真正根本的。前面说的一个原因是C++书籍市场(教育)造就的,然而为什么人们喜欢写这些书呢?进一步说,为什么人们喜欢读这些书呢?
(我承认,我也曾经读得津津有味。)答案很简单:心理。每个人都喜欢戴着脚镣跳舞(事实8)。认识到这一点不是为了提倡它,而是只有当我们认识到自己为什么会津津有味地去钻研一堆补丁解决方案的时候,我们才真正能够摆脱它们的吸引。
总而言之,C++的复杂性只是一个必要条件,并非问题的根本症结。根本症结在于人的心理,每个人都喜欢戴着脚镣跳舞,并且以为是“创新”。意识到这一点之后可以帮我们避免被各种各样名目繁多的语言细节和技巧占去不必要的时间。
然而,C++的复杂性始终是一个不可回避的现实。C++中有大量的陷阱和缺陷,后者导致了数目惊人的惯用法和workarounds。不加选择的全盘预先学习,是非常糟糕的做法,不仅低效,而且根本没有必要,实在是浪费生命。
爱因斯坦曾经说过,“我只想知道‘他’(宇宙)的设计理念,其它的都是细节”。然而,正如另一些读者指出的,如果对C++中的这些细节事先一点都没有概念的话,那么实际编码中一旦遇到恐怕就变成没头苍蝇了,也许到哪里去RTFM都不知道。这也是为什么那么多C++面试都会不厌其烦地问一些有代表性的语言细节的原因。
把细节全盘装在脑子里固然不好,但对细节一无所知同样也不是个办法。那么对于C++程序员来说,在学习中究竟应该以怎样的态度和学习方法来对付C++的复杂性呢?其实答案也非常简单。
首先有一些很重要&必须的语言细节&特性是需要掌握的,然后我们只需知道在C++中大抵有哪些地方有复杂性(陷阱、缺陷),那么遇到问题的时候自然能够知道到哪儿去寻找答案了。具体的建议在后文。 #t#
本来这一节是打算做成一个C++复杂性索引的,然而一来C++的复杂性太多,二来网上其实已经有许多资料(比如Bjarne Stroustrup本人的C++ Technical FAQ就是一个很好的文档),加上市面上的大多数C++书里面也不停的讲语言细节;因此实际上我们不是缺乏资料,而是缺乏一种索引这些资料的办法,以及一种掌控这些复杂性的模块化思维方法。
由于以上原因,这里并不详细罗列C++的复杂性,而是提供一个分类标准。 C++的复杂性有两种分类办法,一是分为非本质复杂性和本质复杂性;其中非本质复杂性分为缺陷和陷阱两类。另一种分类办法是按照场景分类:库开发场景下的复杂性和日常编码的复杂性。从从事日常编码的实践者的角度来说,采用后一种分类可以让我们迅速掌握80%场景下的复杂性。