好語言,就該善用它——《C++語言的設計與演化》讀書筆記

愛飛翔發表於2011-11-09

  C++真是讓人又愛又恨的語言之一。很多人都說C++功能強大,其實很多時候他們都是足夠幸運的,沒有遇到太多需要用程式碼雜技解決的需求,或者沒有親身維護太多充滿“高技巧”的程式碼的專案。我都遇到過,所以最後終於決定把Java當作自己的第一語言。C++作為以愛好為主的研究語言了。

  從2004年開始,我就陸續看了一些C++語言的書。學完C語言後,覺得它在某寫領域過於中級語言化了,我需要一種更高層的抽象方式,所以決定初探C++。那時也未有學習Java或動態語言的想法。一開始看得是入門級別的C++ Primer Plus,流水帳似地把語言的基本功能羅列了一遍,看後沒有學到什麼思路。其次看了較為全面的C++ Primer,這本書又不失深度,講了一些例如虛擬函式表,模板引數推導等高階話題。看完覺得挺有用的,自己試著寫了一個四則運算表示式解析器,挺滿意的。當時我尚未建立物件導向的思想,仍然將C++看待為一個增強版的C工具箱。最後看了兩本重量級的知名書,Effective C++More Effective C++,講了很多關於STL的內容,按我當時的水平接受起來確實有困難,只能說讀完了文字,但是沒有深入的研究。

  直到最近,同事要寫一個遊戲編輯器,用到了QT,所以我又重溫C++了。這次有了Java語言和麵向物件程式設計的經驗,看起來就覺得C++值得深入研究的地方太多了。幸好C++的創始人Bjarne Stroustrup曾經寫過一本《C++語言的設計與演化》,正好拿來當我的複習教材。這本1995年的書,16年後的今天讀來,仍是讓人受益匪淺,尤其是下面這些和我一樣的人一定會有同感:

  1.僅僅將C++作為一個增強的C語言工具包的人。

  2.將C++作為程式碼雜技試練場的人。

  3.對C++語言各種功能不能系統掌握的人。

  書中講到的基本是關於如何設計語言、如何給語言增加新功能、如何標準化一門語言之類的問題。那麼,對於我們這些暫時不會設計一門語言,至多設計類庫、框架乃至終端應用的人來說,可以學到什麼呢?我就摘要地列出幾個有啟發性的章節,與大家探討。

  第三章談新功能的採用。作者認為任何人都能找到增加一個新功能的理由,然而這麼做是不健康的,因為很難保證和既有功能的連貫性。所以,決定增加新功能時,不能單純靠貌似合理的理由,而是要建立在深入實驗的基礎上。

  第六章談到工程質量與語言是否功能多,無必然聯絡。工程質量的提升主要應著眼於設計,而不是眾多花哨的新功能。

  該章還談到是否接受一個新功能的標準:1.是否表述精確,大家是否能夠理解這個功能;2.這個擴充套件的道理是什麼,我們為什麼需要它;3.它是否已經被實現過;4.對既有程式碼的影響;5.對效率和相容性帶來的影響;6.這個改變如何用文件描述,如何教給大家;7.有沒有不引入這個擴充套件的理由;8.有沒有其他方法去實現這個功能。這些標準對庫、框架、應用程式設計者都有參考價值。引入新功能而不破壞既有工程結構的一致性、連貫性,是個很值得下工夫的任務。作者在第九章又重新強調了這一點。

  第八章談到了儘量避免使用強制型別轉換。除了一些系統底層介面,過多的強制型別轉換必然會破壞型別系統。

  第九章還談到C++程式設計師應該將程式看待為型別、函式、語句的資訊集合,而非字元和檔案的集合。

  第十四章至第十七章應該細讀,這四章分別講了C++四個重要的語言功能。執行時資訊識別(RTTI),模板,異常,名稱空間。每一個功能都有一些使用時候的注意事項。例如RTTI不可誤用,只有當設計從外部資訊源(例如文字檔案)中製造物件時,才可以合理的使用。模板可以解決一些對繼承的誤用。如何在C++的終止式異常處理方式下處理需要重試型的異常情況(例如IO錯誤)。如何合理利用名稱空間減少各種庫中名稱的衝突,避免汙染全域性名稱空間。這些都是C++程式設計師經常容易出錯的領域,同時也可以給例如博主這種從Java語言出身的人一個通過比較法來學習語言的機會。

  第十八章也即最後一章,講了巨集(macro)的害處。除了#include之外,應儘量避免用巨集,因為其可以擾亂開發人員對原始碼的理解和維護。尤其是慎用和編譯器的實現相關的#pragma。

  綜觀全書,可以體會到:

  1.C++是一個能非常得體得將功能、設計、執行效率、空間佔用等因素平衡的語言。我們這些類庫、框架、應用設計者,也要在實際程式碼中學習這種平衡的技藝。

  2.對於新功能的加入要十分的謹慎和清醒。切忌破壞既有程式碼、工程、設計的一致性、連貫性、內聚性和可用性。好的工程還是要注重設計。只有功能與設計不脫節,才不會使得過多的新功能難以維護。

  3.對於每一個語言功能的運用,都必須建立在充分理解其設計意圖的基礎上。RTTI,模板,異常都是非常容易被誤用的領域。同理,Java語言的反射,RMI亦然。

  作者用近似編年史的方法回顧了C++主要功能的萌發、構思、實驗、實現、應用這一連貫流程,希望大家和我一樣,在讀這本書的過程中,能夠對C++語言本身,C++和其它語言的比較,以及如何接受與設計新功能,新擴充套件這些問題有一個更深入的瞭解。有很多類似C++這樣的全面、高效、功能豐富的語言,如何善用它,如何用這種語言設計出符合其設計哲學的庫、框架、應用來,這是我們始終應該思考的話題。

(本文為作者原創,如需轉載請聯絡eastarstormlee@gmail.com或http://weibo.com/eastarlee)

相關文章