標籤:
條款05:瞭解C++默默編寫了並調用了那些函數
請記住:
- 編譯器可以暗自為class 建立default建構函式,copy建構函式,copy assignment 操作符,以及解構函式
class Empty{public: Empty(){...} //default constructor Empty(const Empty& rhs){...} //copy constructor ~Empty(){...} //destructor Empty& operator=(const Empty& rhs){...} //copy assignment operator};
條款06:如果不想使用編譯器自動產生的函數就應該明確的拒絕
請記住:
- 為駁回編譯自動(暗自)提供的機能,可將相應成員函式宣告為private並且不予以實現.使用像Uncopyable這樣的base class 也是一種做法。
一旦你定義了自己的建構函式,不論函數參數如何,編譯器都不再自動幫你產生建構函式。
如果你想阻止copying,則要聲明一個private的copy建構函式和copy assignment操作符,並且不去定義它們。這樣,一旦有人嘗試進行copy構造或賦值,編譯器就會報錯。
條款07:為多態的基類,聲明virtual解構函式
請記住:
- polymorphic(帶多態性質的)base class 應該聲明一個virtual解構函式如果class帶有任何virtual 函數,他就該擁有一個virtual解構函式。
- Classes 的設計目的如果不是作為base class 適用,或者不是為了具備多態性質就不該聲明為virual解構函式。
任何class只要帶有virtual函數都幾乎確定應該也有一個virtual解構函式。
如果class不含virtual函數,通常表示它並不意圖被用做一個base class。當class不企圖被當作base class,令其解構函式為virtual往往是個餿主意。
欲實現virtual函數,對象必須攜帶某些資訊,主要用來在運行期決定哪一個virtual函數被調用。這份資訊通常是由一個所謂vptr(virtual table pointer)指標指出。vptr指向一個由函數指標構成的數組,稱為vtbl(virtual table):每一個帶有virtual函數的class都有一個相應的vtbl。當對象調用某一virtual函數,實際被調用的函數取決於該對象的vptr所指的那個vtbl——編譯器在其中尋找適當的函數指標。
如果class內含irtual函數,其對象的體積會增加(由於ptr)。另外,C++的對象也不會和其他語言(如C)內的相同聲明有著一樣的結構(因為其他語言的對應物沒有ptr),因此也不能把它傳遞至(或接受自)其他語言所寫的函數,即不再具有移植性。
條款08:別讓異常逃離解構函式
請記住:
- 解構函式絕對不要吐出異常如果一個被解構函式調用的函數可能拋出異常解構函式應該捕獲任何異常,然後吐下他或者結束程式。
- 如果可會需要對某個操作函數運行期間拋出異常作出反應,那麼class應該提供一個普通函數(而非在解構函式中)執行該操作。
對於C++,有兩個異常同時存在的情況下,程式若不是結束執行,就是導致不明確行為。因此假如某對象的解構函式可能拋出異常,當我們試圖釋放一個包含裝有該類對象的容器時,假設在析構第一個元素期間,有個異常被拋出,容器中的其他元素還是要被銷毀,因此將調用它們各個解構函式,如果在這期間又有另一元素在析構過程中拋出了異常,故事將如何發展便不得而知了。
條款09:絕不在構造和析構過程中調用virtual函數
請記住:
- 在建構函式和解構函式期間不能調用virtual函數因為這類調用從不下降至derived class。
由於base class建構函式的執行更早於derived class建構函式,當base class建構函式執行時derived class的成員變數尚未初始化。如果此期間調用irtual函數下降至derived class階層,要知道derived class的函數幾乎必然取用local成員變數,而那些成員變數尚未初始化。
條款10:令operator=返回一個reference to *this
請記住:
- 令賦值操作符返回一個reference to *this。
條款11:在operator=中處理“自我賦值”
請記住:
- 確保對象自我賦值時operator=有良好的行為,其中技術包括比較“來來源物件”和“目的對象”的地址、精心周到的語句順序,以及 copy-and-swap。
- 確定任何對象操作一個以上的對象,而其中多個對象時同一個對象時,其行為仍然正確。
條款12:賦值對象時勿忘賦值對象的每一個成分
請記住:
- copying 函數應該確保賦值“對象的所有成員變數”有有base class 成分。
- 不要嘗試以某個copying函數實現另一個copying函數,應該將共同的機能放進第三個函數中並由兩個函數共同調用。
當你編寫一個copying函數,請確保(1)複製所有local成員變數,(2)調用所有base class內的適當的copying建構函式,(3)不要嘗試以某個copying函數實現另外一個copying函數。
[Effective C++]構造/析構/賦值運算