在C++里面这样的情况很多见:知道了语言实现的底层机制,却不知道语言特性本身的意义在什么地方,这里将介绍C++教程问题的解决方法,在这里拿出来和大家分享一下。
其实,对于这个问题,Bjarne已经宣传了十年。早在99年的时候Bjarne就写了“Learning C++ as A New Language”,并在好几篇技术访谈(这里,这里,这里,还有这里)里面提到如何正确对待和使用C++中支持的多种抽象机制的问题。
Andrew Koenig也写了一本现代C++教程《Accelerated C++》(这本书后面还会提到)。然而这么多年来,C++社群的状况改善了吗?就我所知,就算有改善,也是很小的。学习者还是盲目钻语言细节,只见树木不见森林;#t#
网上还是弥漫着各种各样的“技术”文章和不靠谱的“学习C++的XX个建议”;一些业界的有身份的专家还是在一本接一本的出语言孔乙己的书(写一些普通程序员八辈子用不着的技巧和碰不着的角落);而业界真正使用C++的公司在面试的时候还总是问一些边边角角的细节问题,而不是考察编程的基本素养(不,掌握所有的语言细节也不能让你成为一个合格的程序员)。
这个面试理念是错误的,估计其背后的推理应该是“如果这个家伙不知道这个细节,那么估计他对语言也熟悉不到哪儿去;而如果他知道,那么虽然他可能并不是好的程序员,但我们还是能够就后一个问题进一步测试的”,这个理念的问题在于对语言熟悉到一定程度(什么程度后面会具体建议)。
就已经可以很好的编程了(剩下的只需查查文档);而很多公司在测试“对语言熟悉程度”的时候走得明显太远了(比如,问临时对象生命期和析构顺序当然是无可厚非的,但问如何避免一个类被拷贝或者如何避免其构建在堆上?);当然,有些语言知识是必须要提前掌握的,具体有哪些后面会提到,面试的时候并非不能问语言细节,关键是“问哪些”。
C++的整个生态圈这么些年来在学习C++的哲学上,实在没有多少改善。 为什么?是因为Bjarne介绍的学习方法在技术上没有说到点子上?是Andrew Koenig的书写得不够好?说了谁也不会相信。因为实际上,这里的原因根本不是技术上的,而是非技术的。
众所周知的一个事实是,从最表层讲,C++教程的最严重问题是在语言学习阶段占用了学习者的太多时间。翻一翻你的C++书架或者电子书目录,绝大多数的C++“经典”都是在讲语言。在我们通常的意义上,要“入门”C++,在语言上需要耗的时间一般要两三年。而要“精通”C++,则搞不好需要耗上十年八年的。(这跟Peter Norvig说的“十年学习编程”其实不是一回事,人家那是说一般意义上的编程技能,不是叫你当语言律师。)
那为什么我说“C++教程的复杂性是根本原因”是个有漏洞的推理呢?因为,要让人们在使用一门语言去做事情之前耗上大量时间去学习语言中各种复杂性,除了语言本身的复杂性的事实之外,还有一个重要的事实,那就是学习者的态度和(更重要的)方法。而目前大多数C++学习者的态度和方法是什么呢?——在真正用C++之前看上一摞语言书(日常编程八辈子都未必用得到)。而为什么会存在这样的学习态度呢?这就是真正需要解释的问题。实际上,有两方面的原因:
事实4:市面上的绝大多数C++书籍(包括很多被人们广泛称为“必读经典”的)实际上都是反面教材。 也就是说,随便你拿起哪本C++书籍(包括很多被人们广泛称为“必读经典”的),那么有很大的可能这本书中的内容不是你应该学的,而是你不应该学的。我之所以这么说有两个原因,因为一,我曾经是受害者。二,也是更实质性的原因,这些所谓的必读经典。
充斥的是介绍C++中的陷阱和对于C++教程的缺陷的各种workarounds(好听一点叫Idioms(惯用法)或techniques(技术));又因为C++中的这类陷阱和缺陷实在数不胜数,所以就拉出了一个“长尾”;这类书籍在所有语言中都存在(“C缺陷和陷阱”、“Effective Java”、“Effective C#”等等),然而在C++里面这个尾巴特别长,导致这类书数不胜数。三,这些书中列出来的缺陷和陷阱根本不区分常见程度。
对于一个用本程序员来说,应该希望看到“从最常见的问题到最不常见的问题”这样的顺序来罗列内容,然而这些书里面要么全部混在一起,要么按照“资源管理、类设计、泛型”这样的技术分类来介绍内容,这根本毫无帮助(如果我看到一个章节的内容,我当然知道它讲的是类设计还是资源管理,还用废话么?),使得一个学习者无法辨别并将最重要的时间花在最常见的问题之上。