【無責任書評:拳拳到肉 擲地鏗鏘的三本 OOP 絕 …
【無責任書評:拳拳到肉 擲地鏗鏘的三本 OOP 絕佳小書】
侯捷 jjhou@ccca.nctu.edu.tw
http://www.jjhou.com
本文將發表於 Run!PC 雜誌 2000/07,並整理於 侯捷網站/散文 2000
----------------------------------------------------------------
拿破崙雖然是個矮個子,一生叱吒卻儼然歷史的巨人。
今天我要介紹的三本書,雖然輕薄短小有如拿破崙的身材,
在 C++/OOP 領域裡,其份量與影響卻也有著拿破崙般的輝煌燦爛。
說它們輕薄短小,是的,讓數字說話:三本書合起來才
256+318+208=782 頁,只比 C++ 語言知名教本 C++ Primer 3/e
一半篇幅再多一些而已,比起 C++ 語言權威著作
The C++ Programming Language 3/e 也才達到三分之二的頁數份量。
逛書店時一個不留神,只怕你便遺漏了這些小書的存在。但如果你真
遺漏了它們的存在,實在是你的莫大損失。
就我個人的編程經驗,以及我的教學經驗(對象為業界工程師或
大學生),只要是 C++/OOP 設計思維與語言運用本身的問題,
非關 problem domain,百分之九十以上皆可在這三本書籍中找到
直接或間接的答案。這三本書是:
●Effective C++ 2/e : 50 Specific Ways to Improve Your Programs and Designs
●More Effective C++ : 35 New Ways to Improve Your Programs and Designs
●Exceptional C++ : 47 Engineering Puzzles, Programming Problems, and Solutions
(註:前兩本書亦有 CD 產品(HTML 格式),以兩書合一的方式出售,
交叉索引甚為方便)
書名副標清楚告訴我們,這些書籍的特色就是以一個個的條款來
說明一些值得奉行或是必須避免的動作。以條款的方式進行,一方面
因為它們都不是 C++ 語言教本,而是更高層次的書籍,是給有語言基礎
(最好還有實際工作經驗)的人看的書,所以可以集中火力在特定主題上,
另一方面實乃因為條款型式可以強化主題,加深印象,提昇查閱檢索
的方便性與價值。
書中某些條款在 C++ 語言書籍裡或多或少也都有提到 — 雖然解釋
的深度可能不足。我舉個例子,Effective C++ 的條款13說
「Initialization list 中的 members 初始化排列次序應該和其在 class 內
的宣告次序相同」,C++ Primer 3/e 的 p721~p722 對此有相同意義的描述。
再舉個例子,Effective C++ 的條款14說
「總是讓 base class 擁有 virtual destructor」,這在 C++ Primer 3/e
的 p933 亦有相同意義的描述。諸如此類,不勝枚舉。但你是不是感覺,
那些金科玉律被淹沒在語言百科型書籍的細節叢林之中!
每一條準則都簡短、明確、容易記憶,可以確實提昇你的軟體效能。
每一條準則都是經驗豐富的 C++ 程式員的心血結晶,告訴你哪些是
幾乎總是需要奉行的動作,哪些是幾乎肯定要避免的事情。
某些條款甚至到達 patterns 的水準(註)。
註:所謂 patterns,在指程式設計過程中,開發人員常需
面對並解決的某些問題,被有系統地整理出解法,謂之 patterns
(或譯為「樣式」)。Design Patterns 是此域中的經典書籍,
系統化地將可應用於眾多領域之 23 個基本 patterns 加以
分類整理。書中所提的 patterns 名稱,幾乎成為物件導向
設計領域的標準辭彙。
以上三本小書的功用不僅在提綱契領地點出重點,也在於對
每個主題有深刻的討論。在這些書籍中,你會發現一些忠告,
告訴你應該做些什麼,為什麼如此;也告訴你不應該做些什麼,
又為什麼如此。基本而言當然 whys 比 whats 更重要,
這便是這些書籍最有價值的地方。至於從速食的角度來看,
檢閱一系列準則,也比強記一或二本龐雜的教科書更輕鬆方便得多。
----------------------------------------------------------
fig1
【基本資料】
書名:Effective C++ 2/e : 50 Specific Ways to Improve Your Programs and Designs
作者:Scott Meyers
出版:Addison Wesley, 0-201-92488-9, 1998
定價:US$ 37.95
頁數:256
Scott Meyers 的這本書籍,成名已久,同時也是此類書籍的濫觴。
這本書在 1992 年便有了第一版,我手上的第一版是 1996/12 的
第 12 刷。刷次原不能代表什麼,不過我在第二版的封底看到,
出版公司宣稱第一版銷售超過十萬本(不含各種譯本)。銷售量
能否代表什麼呢?銷售量低或許不一定能代表什麼,銷售量高則
相當程度地表示受到讀者的肯定。以此書訴求之技術層面而言,
這個銷售量是驚人的。(當然要是比起大陸某 C 語言書籍銷售
270 萬本,以及某 Visual Basic 書籍銷售破千萬本,那是小巫
見大巫了)
只要是在 C++ 領域裡打滾的程式員,馬上便可以從 Meyers 整理
出來的 50 個條款看出此書的價值。如果你拿 C++ 來討生活,
稍稍閱讀幾個條款的深度後,不掏腰包者幾稀。有些條款涉及的語意
層面較低,用以對容易出錯或混淆的數種程式寫法提出警告。另有
一些條款涉及的層次比較高,如第六章中對於各種繼承型式的討論、
以及 classes 之間除了繼承以外的其他關係的討論。至於條款E45
「知道 C++ 編譯器默默為我們完成和呼叫哪些函式」,以及
條款M24「瞭解 virtual functions、multiple inheritance、
virtual base classes、RTTI 所需的成本」,下涉物件模型與編譯器層面,
相當深入。套用我過去在「C++ 的沉迷與愛戀」一文中所用的辭,
此書在高熱和驟冷之間,在高階和低階之間焠鍊、循環、震盪。
本書第一頁列有它所獲得的讚譽。對於讀者,這是一份值得參考的資料,
我試著把它們譯為中文,條列於下:
※我必須真心地讚美 Meyers 的書,…這本書在記憶體管理架構
等主題上給予讀者卓越的引導,並對不同型式之 C++ 繼承機制
有極佳的解釋。
- New York Computerist
※在你開始著手第一個真正的 C++ 專案之前,你應該閱讀本書;
在你獲得一些實務經驗之後,你應該再讀一遍。
- comp.lang.c++
※本書有一個子標題「改善你的程式技術與設計思維的 50 個
有效作法 」。作者不只提供你撰寫 C++ 碼時應該遵循的明白
規則,也提供了深入的解釋與範例。
- Sun Expert
※我慎重推薦 Effective C++ 給任何渴望在中高階層面精通
C++ 的人。
- The C User's Journal
※在各種寫給中高階程式員看的 C++ 書籍中,這是我所見過
最棒的一本。作者以一系列短文敘述 C++ 程式員遭遇的常見
問題。…本書既有趣又有用,在程式設計書籍中誠屬罕見。
- comp.lang.c++
※本書在取材範圍和風味上類似另一本由 William Strunk
和 E.B. White 合著的小書 The Eements of Style;至少
二者在我的書架上距離不遠。…這是一本十分謹慎而適度的
小書,有著清楚的目標,並且完成了它們。
- C++ Report
※這本書內含對 C++ 開發工作的許多實用忠告。
- DEC Professional
※C++ 程式員不只應該擁有這本書,而且應該確實運用這本書。
書中的文字極易拿來實際運用。交叉參考與索引的功夫做得很好。
- Computer Language
※這是一本 193 頁的傑作。…我保證 50 個條款中必定有
某一些會攫取你的注意力並對你產生啟蒙作用,你的謹慎
投資將獲得回報。…這是一本文筆優越、真材實料的書籍,
目標瞄準重視流暢與效率的所有 C++ 程式員。
- Stan Kelley-Bootle, UNIX Review
※這本絕妙好書提供了 50 個招數,幫助我們把 C++ 運用得
更好。每一位 C++ 程式員桌上都應該有這一本書。…在
提昇 C++ 程式設計的整體品質上, Scott Meyers 這份
珍貴的禮物或許比業內任何人士的貢獻都大。』
-- Jesse Liberty, C++ Report
下面列出 Effective C++ 2/e 的各個條款(我試著譯為中文),
一方面讓這篇書評的實用性更高一些,一方面就讓這些條款標題
直接彰顯它們的價值吧。
第一章:改變舊有的 C 習慣
條款1:儘量以 const 和 inline 取代 #define
條款2:儘量以 <iostream> 取代 <stdio.h>
條款3:儘量以 new 和 delete 取代 malloc() 和 free()
條款4:儘量使用 C++ 風格的註解型式
第二章:記憶體管理(Memory Management)
條款5:使用相同型式的 new 和 delete
條款6:記得在 destructor 中以 delete 對付 pointer members
條款7:為記憶體不足的狀況預做準備
條款8:撰寫 operator new 和 operator delete 時應遵行公約
條款9:避免遮掩了 new 的正規型式
條款10:如果你寫了一個 operator new,請對應也寫一個 operator delete
第三章:建構式,解構式,和 Assignment 運算子
條款11:如果 classes 內動態配置有記憶體,請為此 class 宣告一個 copy constructor
和一個 assignment 運算子
條款12:在 constructor 中儘量以 initialization 取代 assignment
條款13:Initialization list 中的 members 初始化排列次序應該和其在 class 內的宣告
次序相同
條款14:總是讓 base class 擁有 virtual destructor
條款15:令 operator= 傳回「*this 的 reference」
條款16:在 operator= 中為所有的 data members 指派內容
條款17:在 operator= 中檢查是否「自己派給自己」
第四章:類別與函式之設計和宣告
條款18:努力讓介面完滿且最小化
條款19:區分 member functions, non-member functions 和 friend functions 三者
條款20:避免將 data members 放在公開介面中
條款21:儘可能使用 const
條款22:儘量使用 pass-by-reference(傳址),少用 pass-by-value(傳值)
條款23:當你必須傳回 object 時,不要嘗試傳回 reference
條款24:在函式多載化(function overloading)和參數預設化(parameter defaulting)
之間,謹慎抉擇
條款25:避免對指標型別和數值型別進行多載化
條款26:防衛潛伏的 ambiguity(模稜兩可)狀態
條款27:如果不想使用編譯器暗自產生的 member functions,就應該明白拒絕它
條款28:嘗試切割 global namespace(全域命名空間)
第五章:類別與函式之實作
條款29:避免傳回內部資料的 handles
條款30:避免寫出 member function,傳回一個 non-const pointer 或 reference 並以之
指向較低存取層級的 members
條款31:千萬不要傳回「函式內 local 物件的 reference」,或是「函式內以 new 獲得的
指標所指的物件」
條款32:儘可能延緩變數定義式的出現
條款33:明智地運用 inlining
條款34:將檔案之間的編譯依存關係(compilation dependencies)降至最低
第六章:繼承機制與物件導向設計
條款35:確定你的 public inheritance 模塑出 "isa" 的關係
條款36:區分「介面繼承(interface inheritance)」和「實作繼承(implementation
inheritance)」
條款37:絕對不要重新定義一個繼承而來的非虛擬函式
條款38:絕對不要重新定義一個繼承而來的預設參數值
條款39:避免在繼承體系中做 cast down(向下轉型)的動作
條款40:透過 layering(分層技術)來模塑 has-a 或 is-implemented-in-terms-of 的關
係
條款41:區分 inheritance 和 templates
條款42:明智地運用 private inheritance(私有繼承)
條款43:明智地運用多重繼承(multiple inheritance,MI)
條款44:說出你的意思並瞭解你所說的每一句話
第七章:雜項討論(Miscellany)
條款45:知道 C++(編譯器)默默為我們完成和呼叫哪些函式
條款46:寧願編譯和聯結時出錯,也不要執行時才錯
條款47:使用 non-local static objects 之前先確定它已有初值
條款48:不要對編譯器的警告訊息視如不見
條款49:儘量讓自己熟悉 C++ 標準程式庫
條款50:加強自己對 C++ 的瞭解
-------------------------------------------------------------------
fig2
【基本資料】
書名:More Effective C++ : 35 New Ways to Improve Your Programs and Designs
作者:Scott Meyers
出版:Addison Wesley, 0-201-63371-X, 1996
定價:未標示
頁數:318
繼 Effective C++ 之後,Scott Meyers 於 1996 推出這本
「續集」。條款變得比較少,頁數倒是多了一些,原因是
這次選材比「第一集」更高階,尤其是第五章。Meyers 將
此章命名為技術(Techniques),並明白告訴你,其中都是
一些 patterns,例如 virtual ctors、smart pointers、
reference counting、proxy classes,double dispatching…
等等。這一章的每個條款篇幅都在 15~30 頁之譜,實在讓人有
「山窮水盡疑無路,柳暗花明又一村」之嘆。
雖然出版年代稍嫌久遠,本書並沒有第二版,原因是當其
出版之時(1996),C++ Standard 已經幾乎定案,本書
即依當時的標準草案而寫。其間與現今之 C++ 標準規格
幾乎相同。可能變化的幾個彈性之處,Meyers 也都有所
說明與提示。讀者可以連結作者提供的網址,看看上下兩集
的勘誤與討論(數量之多,令人驚恐。幸好多是技術討論
或文字斟酌,並沒有什麼重大誤失)。
本書第一頁列有它所獲得的讚譽。對於讀者,這是一份值得參考
的資料,我試著把它們譯為中文,條列於下:
※這是一本多方面發人深省的 C++ 書籍:不論在你偶爾用到的
語言特性上,或是在你自以為十分熟悉的語言特性上。只有深刻
瞭解 C++ 編譯器如何解釋你的碼,你才有可能以 C++ 語言寫出
穩健強固的軟體。本書是協助你獲得此等層級之瞭解過程中,
一份極具價值的資源。讀過本書之後,我P覺像是瀏覽了 C++
程式大師所檢閱過的碼,並獲得許多極具價值的洞見。
- Fred Wild, Vce President of Technology,
Advantage Software echnologies
※本書內含大量重要的技術,這些技術是撰寫優良 C++ 程式所
不可或缺的。本書解釋如何設計和實作這些觀念,以及潛伏在
其他某些替代方案中的陷阱。本書亦含晚近加入之 C++ 特性的
詳細說明。任何人如果想要好好地運用這些新特性,最好買一本
並且放在隨手可得之處,以備查閱。
- Chrisopher J. Van Wyk, Professor
Mahematics and Computer Science, Drew University
※這是一本具備工業強度的最佳書籍。對於已經閱讀過 Effetive C++
的人,這是完美的續集。
- Eric Nagler, ++ Instructor and Author,
Univesity of California Santa Cruz Extension
※More Effective C++ 是一本無微不至而且價值不扉的書籍,
是 Scott 第一本書 Effective C++ 的續集。我相信每一位
專業的 C++ 軟體開發人員都應該讀過並記憶 Effective C++
和 More Effective C++ 兩本書內的各種招式,以及其中重要
(並且有時候不可思議)的語言面向。我強烈推薦這兩本書給
軟體開發人員、測試人員、管理人員…,每個人都可以從 Scott
專家級的知識與卓越的表達能力中獲益。
- Steve Burkett, Software Consutant
以下列出 More Effective C++ 的各個條款(我試著譯為中文),
一方面讓這篇書評的實用性更高一些,一方面就讓這些條款標題
直接彰顯它們的價值吧。
第一章:基礎議題(Basics)
條款1:仔細區別 pointers 和 references
條款2:最好使用 C++ 轉型運算子
條款3:絕對不要以 polymorphically(多型)方式來處理陣列
條款4:非必要不使用 default constructor
第二章:運算子(Operators)
條款5:對自定的型別轉換函式保持警覺
條款6:區別 increment/decrement 運算子的前序(prefix)和後序(postfix)型式
條款7:千萬不要多載化 &&, ||, 和 , 運算子
條款8:瞭解各種不同意義的 new 和 delete
第三章:異常情況(Exceptions)
條款9:利用 destructors 避免遺失資源
條款10:在 constructors 內阻止資源的遺失(resource leaks)
條款11:禁止異常訊息(exceptions)流出 destructors 之外
條款12:瞭解「丟出一個 exception」與「傳遞一個參數」或「呼叫一個虛擬函式」之間的
差異
條款13:以 by reference 方式捕捉 exceptions
條款14:明智運用 exception specifications
條款15:瞭解異常處理(exception handling)的成本
第四章:效率(Efficiency)
條款16:謹記 80-20 法則
條款17:考慮使用 lazy evaluation
條款18:分期攤還預期的計算成本
條款19:瞭解暫時性物件的來源
條款20:協助完成「傳回值最佳化(RVO)」
條款21:利用多載化技術(overload)避免隱式型別轉換
條款22:考慮以運算子的複合型式(op=)取代其獨身型式(op)
條款23:考慮使用其他程式庫
條款24:瞭解 virtual functions、multiple inheritance、virtual base classes、
runtime type identification 所需的成本
第五章:技術(Techniques,又稱 Idioms 或 Pattern)
條款25:將 constructor 和 non-member functions 虛擬化
條款26:限制某個 class 所能產生的物件數量
條款27:要求(或禁止)物件產生於 heap 之中
條款28:Smart Pointers(精靈指標)
條款29:Reference counting(參用計數)
條款30:Proxy classes(替身類別、代理人類別)
條款31:讓函式根據一個以上的物件型別來決定如何虛擬化
第六章:雜項討論(Miscellany)
條款32:在未來時態下發展程式
條款33:將非尾端類別(non-leaf classes)設計為抽象類別(abstract classes)
條款34:如何在同一個程式中結合 C++ 和 C
條款35:讓自己習慣使用標準的 C++ 語言
-------------------------------------------------------------------
fig3
【基本資料】
書名:Exceptional C++ : 47 Engineering Puzzles, Programming Problems, and
Solutions
作者:Herb Sutter
出版:Addison Wesley, 0-201-61562-2, 1999
定價:US$ 33.95
頁數:206
相較於前兩本威名遠播的老大哥,這本小書不但資歷淺,作者
也似乎不是那麼有名。真的不那麼有名嗎?未必,這要
看你熟悉哪個領域,在哪個領域活動而定。本書內容源自極受
歡迎的 C++ 網際網路節目 Guru of the Week,作者
Herb Sutter 正是這個網路節目的創辦者,同時也是
C++ Report 的專欄作家,以及網際網路討論群
comp.lang.c++.moderated 的創始主持人。
本書的一個最大特色是,以實例進行的方式,告訴你如何
以標準 C++ 進行軟體工程。書中所列的實例,有些是
棘手的 C++/OOP 疑難雜症,有些展示穩健強固且具擴充性的程式碼。
只需數分鐘時間,你便可以拿書中一些 C++ 設計問題和
實作問題來挑戰自己並且獲得樂趣(是的,每個問題都有一個難度評分)。
每一個實例,都可以測驗你的觀念正確與否。書中許多主題與
Effective C++ 和 More Effective C++ 的條款相互輝映,
一個實例之中可能隱含了 Meyers 兩本書的數個條款的運用。
順帶一提,這本書有老大哥 Scott Meyers 寫序推薦。
以下列出 Exceptional C++ 的各個條款(我試著譯為中文),
Sutter 下標題的方式不像 Meyers 那麼具有實用性。不過,
這些標題大略呈現了本書的方向,所以,還是讓它們自我說明吧。
第一章:泛型程式設計與 C++ 標準程式庫
條款1:Iterators(泛型指標)
條款2:無分大小寫的字串 之一
條款3:無分大小寫的字串 之二
條款4:將泛型容器(Generic Containers)的重用性擴張至最大 之一
條款5:將泛型容器(Generic Containers)的重用性擴張至最大 之二
條款6:暫時物件
條款7:使用標準程式庫(再談暫時物件)
第二章:Exception-Safety(異常情況下仍然安全)的主題與相關技術
條款8: 撰寫 Exception-Safe 程式碼 之一
條款9: 撰寫 Exception-Safe 程式碼 之二
條款10:撰寫 Exception-Safe 程式碼 之三
條款11:撰寫 Exception-Safe 程式碼 之四
條款12:撰寫 Exception-Safe 程式碼 之五
條款13:撰寫 Exception-Safe 程式碼 之六
條款14:撰寫 Exception-Safe 程式碼 之七
條款15:撰寫 Exception-Safe 程式碼 之八
條款16:撰寫 Exception-Safe 程式碼 之九
條款17:撰寫 Exception-Safe 程式碼 之十
條款18:程式碼複雜度 之一
條款19:程式碼複雜度 之二
第三章:Class 的設計與繼承
條款20:Class 技術
條款21:改寫(Overriding)虛擬函式
條款22:Classes 之間的關係 之一
條款23:Classes 之間的關係 之二
條款24:使用/禁用 繼承(Inheritance)
條款25:物件導向程式設計
第四章:編譯器防火牆(Firewalls)及 Pimpl Idiom
條款26:將編譯時期的依存性最小化 之一
條款27:將編譯時期的依存性最小化 之二
條款28:將編譯時期的依存性最小化 之三
條款29:編譯防火牆(Compilation Firewalls)
條款30:The "Fast Pimpl" Idiom
第五章:名稱查詢(Name Lookup)、命名空間(Namespaes)、介面準則(Interface
Principle)
條款31:名稱查詢與介面準則 之一
條款32:名稱查詢與介面準則 之二
條款33:名稱查詢與介面準則 之三
條款34:名稱查詢與介面準則 之四
第六章:記憶體管理
條款 35:記憶體管理 之一
條款 36:記憶體管理 之二
條款 37:auto_ptr
第七章:陷阱、易犯錯誤與反常作法
條款 38:物件識別(Object Identity)
條款 39:自動轉換(Automatic Conversions)
條款 40:物件壽命(Object Lifetimes)之一
條款 41:物件壽命(Object Lifetimes)之二
第八章:雜項主題
條款 42:變數的初始化
條款 43:常數性的正確性(Const-Correctness)
條款 44:轉型(Casts)
條款 45:真假值(bool)
條款 46:轉呼叫(Forwarding)函式
條款 47:控制流程(Control Flow)
●結語
理論與實務的結合,是每一位資訊從業人員希望達到的目標。
過多的照本宣科,過少的實務經驗(真正有價值的實務經驗),
卻是目前資訊相關書籍的普遍寫照。
Effective C++,More Effective C++, 和 Exceptional C++,
這三本書不僅在實務面上提出極為寶貴的準則,並以
豐富而紮實的理論基礎,深入解釋每一條準則背後的來龍去脈。
可以相當程度地提昇你的 C++ 程式技術與 OO 設計思維。
著名的語言專家 Benjamin Whorf 曾說:『語言可以塑造人類
思考的方式,並決定人類思考的內容』。使用 C++ 語言,
絕不僅只於使用 C++ 編譯器(很多人確是如此 — 雖然他們不自覺);
重要的是運用隱含於語意之中的物件導向(Object Oriented)觀念
與泛型(Genericity)觀念,在軟體設計階段便創造出一個
有彈性、易修改、適用未來時態的架構。
對於物件導向領域的生手,這三本書可以給你一個震憾教育,
讓你知道過去的寫作是多麼地不嚴謹、觀念是多麼地不成熟。
或許這套書會促使很多自以為是的讀者謙卑地認知自我的不足,
並謙卑地終於知道什麼是井蛙、河魚和燕雀。
至於物件導向箇中老手,是的,這三本書為你整理出多年打滾
所獲的寶貴心得,佐以深度的學理探討,必然讓你有相見恨晚之嘆。
-- the end
--
※ Origin: 楓橋驛站<bbs.cs.nthu.edu.tw> ◆ Mail: jjhou@ccca.nctu.edu.tw
CompBook 近期熱門文章
PTT數位生活區 即時熱門文章