關于函數體 try 的幾個要點:
- 構造函數 try 只能用來傳遞從基類或成員子對象的構造函數拋出的對象(或者做一些響應這些錯誤的其它操作),不能用作其它用途(比如釋放資源)。
- 析構函數 try 沒有什么實際用途,因為析構函數不應該拋出異常。
- 所有其它的函數 try 沒有什么實際用途。一個一般的函數 try 不能抓取到函數體內的 try 所不能抓取到的異常。
- 記住在構造函數體內而不是在初始化列表中分配未被管理的資源(比如使用 new)。即,要么使用“獲取資源就是初始化”,從而避免未被管理的資源,要么在構造函數體內獲取資源。
- 總是在構造函數或析構函數體內釋放未被管理的資源,而不是在它們的函數 try 里面。
- 如果一個構造函數有異常規格,那么它的異常規格必須包含該類的基類和成員子對象的所有可能拋出的異常。
- 使用 Pimpl 思想來保持類內部的“可選的部分”。如果一個成員對象的構造函數可能拋出異常而你不一定需要那個對象,就可以在類中僅僅保持一個指向該對象的指針。通過該指針是否為空來判斷是否持有改對象。
- 最后重復一下:使用“資源分配就是初始化”而不是手動管理資源。
文章來源:
http://my.donews.com/robinchow/2007/01/29/cagxxmzwktgtrdirlmuspfjuarcxkcumdbjb/
標準 uncaught_exception() 函數提供了對是否還有活動異常的判斷。非常值得注意的是,它不表明是否可以安全地拋出異常。
指導原則:
- 千萬不要從析構函數內拋出異常。原因是如果當存在另一個活動異常,而析構函數又拋出一個異常時(堆棧展開時),程序將被終止。寫析構函數時加上空的異常規格,因為異常規格將帶來額外的代價,因此可以將它寫成注釋的形式。
- 如果析構函數調用一個可能拋出異常的函數,一定要將它包含在一個 try/catch 塊內以防止異常傳出。
最后一點,uncaught_exception() 沒有安全的用途,因此建議不要使用。
文章來源:
http://my.donews.com/robinchow/2007/01/29/jxfinmwnxhfofnvifzmrkqjgteyknbfxzlfn/
關于參數表達式求值:
- 在函數調用之前,函數的所有參數都必須完成求值。這包括了參數表達式求值的所有副作用。
- 一旦函數開始執行,則調用函數的所有表達式要等到被調函數執行完成之后才開始或繼續求值。函數的執行不會相互間接。
- 函數的參數表達式求值的順序不定,可能互相間接。
f(new T1, new T2) 可能導致一個經典的內存泄漏問題。加入 new T1 先執行,new T2 后執行,則一旦 new T2 的過程拋出異常,T1 的內存將被泄漏。
文章來源:
http://my.donews.com/robinchow/2007/01/29/vcdrqtzdfdhbnkjyqgipqoiapasnrtvmwydm/
關于臨時對象:臨時對象在包含它的創建點的全部表達式的最后一步被銷毀。甚至在全部表達式拋出異常時也是如此。
編碼標準:不要在同一表達式中編寫分配資源而且可能拋出異常的代碼。即使分配的資源會立即被管理(例如傳遞給 auto_ptr 的構造函數)。
更簡單的方法是:對每個單獨的資源分配,都放在單獨的代碼片斷里,而不是將幾個資源分配放在同一個表達式中。然后再將分配的資源傳遞給管理對象(auto_ptr)進行管理。
文章來源:
http://my.donews.com/robinchow/2007/01/30/pvtqocosqslbdxledtwmymsmgcfifqavmula/
設計方法:
低耦合有利于程序的正確性(包括異常安全),而高耦合則減降低了程序最大可能的正確性。
繼承通常被濫用,甚至一些經驗豐富的開發人員也是如此。盡量降低耦合。如果類的關系能夠用多種方式表達,那么選用關系最弱的方式。特別是,只有在代理不夠用的時候才使用繼承。
文章來源:
http://my.donews.com/robinchow/2007/02/03/veyjfchfekvqisvephpmjlwafvknmahifgrl/
關于多繼承(MI):
避免從超過一個的非協議類進行多繼承。協議類是指抽象基類,僅由純虛函數組成,而沒有數據。
實際使用多繼承時不外乎一下三種情況:
- 將幾個模塊或者庫結合起來。
- 協議類。這是多繼承最好、最安全的用法。
- 易用性(多態)。
另外,記住有時候不是僅僅從兩個不同的基類繼承,而是以不同的理由各自進行繼承。例如,可以對一個基類進行私有繼承以訪問基類的保護成員,同時對另一個基類進行公有繼承以實現多態。
文章來源:
http://my.donews.com/robinchow/2007/02/03/cbkweueolxssxwokmhjkcwizyhjjhdfkepgj/
純虛函數是具體派生類必須重載的虛函數。如果一個類有一個沒有重載的純虛函數,那么它是一個抽象類,不能創建該類型的對象。
定義純虛函數體的原因有以下死點:
- 純虛析構函數。通常情況下,析構函數要么是虛函數并且為公有,要么是非虛函數并且為 protected。如果沒有提供函數定義,則不能實例化該基類的派生類。
- 強迫程序員認識到正在使用缺省行為。對于普通虛函數,如果派生類沒有重載則默認使用基類的缺省行為。如果不想隱含地使用基類的行為,可以使基類的虛函數為純虛函數,則派生類必須顯式地使用基類的行為。
- 提供部分行為。
- 幫助編譯器診斷錯誤。如果不小心調用了一個純虛函數(通常是對構造函數或析構函數間接調用),編譯器可能查不到問題所在,這是可以在純虛構函數里面寫一些使程序崩潰的代碼,從而方便進行查錯。
文章來源:
http://my.donews.com/robinchow/2007/02/05/rhawrggrcrbpbeslbvcspydjubkcgkwxswuj/
局部類型或匿名類不能用作模板參數。
C++ 不支持函數嵌套,但是我們可以通過函數對象來間接實現它。
#
數字符(或稱‘字符串化’操作符)把擴展后的宏參數轉化成字符串常量。 它僅與帶參數的宏一起使用。
如果它在宏定義中定義在形參前面,那么由宏調用傳遞進來的實參是被引號括起來的,并且被當做一個字符串語意來對待。
這個字符串會替代每一個在宏定義中出現的‘字符串化’的操作符和形參。
符號傳遞操作符
雙數字符(或稱“符號傳遞”操作符),有時也被稱為合并操作符,用在類似對象以及類似函數的宏中。 它允許分開的若干符號被合并成一個符號,因此它(##)不能作為宏定義中第一個或者最后一個出現的符號。
除了以下情況,盡量避免使用預處理宏:
- #include 守衛
- 增強可移植性或方便調試的條件編譯(在 cpp 文件中,而不是在 .h 文件中)。
- 使用 #pragmas 來禁止一些無意義的警告。#pragmas 通常應該放在 “移植性的條件編譯” 守衛中以防止編譯器不能識別該指令而發出警告。
文章來源:
http://my.donews.com/robinchow/2007/02/11/wkibsjwatiheajluxlmvybkwnutbvifrtotm/
使用宏時須注意:
- 參數兩邊要加括號
- 整個表達式兩邊要加括號
- 特別注意表達式多次求值的情況,如 max(++i, j)
- 宏會攪亂名字空間
- 宏不能遞歸
- 宏沒有地址
- 宏不利于調試
On a compliant compiler, it is not possible for a macro to create any of the following:
a trigraph (trigraphs are replaced in phase 1);
a universal character name (\uXXXX, replaced in phase 1);
an end-of-line line-splicing backslash (replaced in phase 2);
a comment (replaced in phase 3);
another macro or preprocessing directive (expanded and executed in phase 4); or
changes to a character literal (for example, 'x') or string literal (for example, "hello, world") via macro names inside the strings.
文章來源:
http://my.donews.com/robinchow/2007/02/11/bavcdirqeacybkdedpxorhuddpwyehtghojl/
將字符轉換為字節:
byte[] byteTime = Encoding.ASCII.GetBytes(DateTime.Now.ToString());
將字節轉換為字符:
string sTime = Encoding.ASCII.GetString(bytes,0,bytesRead);
文章來源:
http://my.donews.com/robinchow/2007/03/25/c-%e4%b8%ad%e5%ad%97%e7%ac%a6%e5%92%8c%e5%ad%97%e8%8a%82%e7%9b%b8%e4%ba%92%e8%bd%ac%e6%8d%a2/