條款47:請使用traits classes表現類型信息
? ? ? ? STL有五類迭代器分類,input迭代器(只讀,一次,向前)、output迭代器(可寫,一次,向前)、forward迭代器(讀/寫,多次)、Bidrectional迭代器(雙向)、random access迭代器(任意跳躍,雙向);
? ? ? 當函數、類或一些封裝的通用算法的某些部分會因為數據類型不同而導致處理或邏輯不同,traits是一個很好的解決方案;traits是一種技術,它對內置類型和用戶自定義類型的表現必須一樣好;
? ? ? 實現traits技術的方法:1)確定若干你希望將來可取得的類型相關信息;2)為該信息選擇一個名稱;3)提供一個template和一組特化版本內含你支持的類型;實現的方式是通過if..else語句來實現(運行期判斷),但是我們確定模板是在編譯期,如何將這兩個統一起來,方法就是重載(可以讓traits classes在編譯器對類型執行if..else測試);具體代碼如下:
條款48:認識template元編程
? ? ? ? ? TMP有兩個偉大的努力,第一:它讓某些事情更容易;第二,由于template metaprograms執行于C++編譯器,因此可將工作從運行期轉移到編譯器(原先在運行期的錯誤,現在在編譯期就能發現),導致較小的可執行文件,較短的運行期、較少的內存需要,但是導致編譯期變長;
條款49:了解new-handler行為
? ? ? ? ?當opertor new無法滿足某一內存分配需求時,它會調用一個客戶指定的錯誤處理函數,一個所謂的new_handle;代碼如下:
? ? ??
new_handle是個typedef,定義一個指針指向函數,函數無參數也沒有返回值;set_new_handle的參數是一個指針,指向operator new無法分配足夠內存時該被調用的函數,返回值也是一個指針,指向set_new_handler被調用真在執行(馬上被替換)的那個new_handler函數;
? ? ? 一個設計良好的new_handle函數必須做的事情有:1)分配更多內存可被使用;2)安裝另外一個new_handler,如果當前的new_handle沒辦法處理這個事情;3)卸載new_handler,將null指針傳給set_new_handle;4)拋出bad_alloc異常;5)不返回,通常調用abort( )和exit;
? ? ? 當這種情況牽涉到模板時,需要采用template,一種簡單的做法就是建立一個“mixin”風格的base class,這種base class用來允許derive的 classes繼承單一特定能力;代碼如下:
? ? ?代碼的怪異支出在于以widget調用widget模板,這個稱為怪異的循環模板模式,雖然里面繼承的是模板類,但是類中卻沒有用到模板定義的類型,這種做法的目的只是為了讓每一個class里面的static成員變量都不一樣;
? ? ? 除了operator new之外還有一種內存分配方式,稱為nothrow形式,正常分配則返還指向內存的指針,否則返回nullptr;
條款53:不要忽視編譯器的警告
? ? ? ? 嚴肅對待編譯器給出的警告,努力在你的編譯器最高警告級下通過代碼;
? ? ? ?不要過渡依賴編譯器,不同的編譯器對待事情的態度不一樣;
條款54:讓自己熟悉包括TR1在內的標準程序庫
? ? ? ? ? ?C++98列入的標準程序庫:STL(容器,迭代器,算法,函數對象,容器適配器,函數對象適配器),Iostream,國際化支持(多區域能力),數值處理(復數和純數值模板),異常階層體系,c89標準程序庫;
? ? ? ? ? TR1內的14個新組件:智能指針,function對象,bind綁定器,Hash tables, 正則表達式,Tuples(變量組),tr1::array,tr1::mem_fn,tr1::reference_wrapper,Typer traits,tr1::result of;
條款55:讓自己熟悉boost
? ? ? ? ? boost程序庫對付的主題有十多個:1)字符串和文本處理;2)容器;3)函數對象和高級編程;3)泛型編程;4)模板元編程;5)數學和數值;6)正確性和測試;7)數據結構;8)語言間的支持;9)內存;10)雜項;