15.4. 建構函式和複製控制
1、建構函式和複製控制成員不能繼承,每個類定義自己的建構函式和複製控制成員。
15.4.1. 基類建構函式和複製控制
1、本身不是派生類的基類,其建構函式和複製控制基本上不受繼承影響。
15.4.2. 派生類建構函式
1、派生類的建構函式受繼承關係的影響,每個派生類建構函式除了初始化自己的資料成員之外,還要初始化基類。
合成的派生類預設建構函式
2、派生類的合成預設建構函式與非派生的建構函式只有一點不同:除了初始化派生類的資料成員之外,它還初始化派生類物件的基類部分。基類部分由基類的預設建構函式初始化。
定義預設建構函式
向基類建構函式傳遞實參
3、派生類建構函式的初始化列表只能初始化派生類的成員,不能直接初始化繼承成員。相反派生類建構函式通過將基類包含在建構函式初始化列表中來間接初始化繼承成員。
4、建構函式初始化列表為類的基類和成員提供初始值,初始化列表並沒有指定初始化的執行次序。首先初始化基類,然後根據宣告次序初始化派生類的成員。
在派生類建構函式中使用預設實參
5、當然,派生類 建構函式可以被編寫為乙個接受預設實參的建構函式,為每個形參提供了預設值。
只能初始化直接基類
6、乙個類只能初始化自己的直接基類。
15.4.3. 複製控制和繼承
1、合成操作對物件的基類部分連同派生部分的成員一起進行複製、賦值或撤銷。基類部分成員使用基類的複製建構函式、賦值操作符或析構函式進行複製、賦值或撤銷。
2、類是否需要定義複製控制成員完全取決於類自身的直接成員。只包含類型別或內建型別資料成員、不含指標的類一般可以使用合成操作,複製、賦值或撤銷這樣的成員不需要特殊控制。具有指標成員的類一般需要定義自己的複製控制來管理這些成員。
定義派生類複製建構函式
3、如果派生類顯式定義自己的複製建構函式或賦值操作符,則該定義將完全覆蓋預設定義。被繼承類的複製建構函式和賦值操作符負責對基類成分以及類自己的成員進行複製或賦值。
4、如果派生類定義了自己的複製建構函式,該複製建構函式一般應顯式使用基類複製建構函式初始化物件的基類部分:
class base ;
class derived: public base
};初始化函式 base(d) 將派生類物件 d 轉換(第 15.3 節)為它的基類部分的引用,並呼叫基類複製建構函式。如果省略基類初始化函式,如下**:
// probably incorrect definition of the derived copy constructor
derived(const derived& d) /* derived member initizations */
效果是執行 base 的預設建構函式初始化物件的基類部分。假定 derived 成員的初始化從 d 複製對應成員,則新構造的物件將具有奇怪的配置:它的 base 部分將儲存預設值,而它的 derived 成員是另一物件的副本。
派生類賦值操作符
5、賦值操作符通常與複製建構函式類似:如果派生類定義了自己的賦值操作符,則該操作符必須對基類部分進行顯式賦值。
派生類析構函式
6、析構函式的工作與複製建構函式和賦值操作符不同:派生類析構函式不負責撤銷基類物件的成員。編譯器總是顯式呼叫派生類物件基類部分的析構函式。每個析構函式只負責清除自己的成員:
class derived: public base
};物件的撤銷順序與構造順序相反:首先執行派生析構函式,然後按繼承層次依次向上呼叫各基類析構函式。
15.4.4. 虛析構函式
1、刪除指向動態分配物件的指標時,需要執行析構函式在釋放物件的記憶體之前清除物件。處理繼承層次中的物件時,指標的靜態型別可能與被刪除物件的動態型別不同,可能會刪除實際指向派生類物件的基類型別指標。如果刪除基類指標,則需要執行基類析構函式並清除基類的成員,如果物件實際是派生型別的,則沒有定義該行為。要保證執行適當的析構函式,基類中的析構函式必須為虛函式。如果析構函式為虛函式,那麼通過指標呼叫時,執行哪個析構函式將因指標所指物件型別的不同而不同:
2、如果層次中根類的析構函式為虛函式,則派生類析構函式也將是虛函式,無論派生類顯式定義析構函式還是使用合成析構函式,派生類析構函式都是虛函式。
3、三法則指出,如果類需要析構函式,則類幾乎也確實需要其他複製控制成員。基類幾乎總是需要建構函式,從而可以將析構函式設為虛函式。如果基類為了將析構函式設為虛函式則具有空析構函式,那麼,類具有析構函式並不表示也需要賦值操作符或複製建構函式。
4、即使析構函式沒有工作要做,繼承層次的根類也應該定義乙個虛析構函式。
建構函式和賦值操作符不是虛函式
5、在複製控制成員中,只有析構函式應定義為虛函式,建構函式不能定義為虛函式。建構函式是在物件完全構造之前執行的,在建構函式執行的時候,物件的動態型別還不完整。
c primer閱讀筆記 15章 1
1 物件導向程式設計基於三個基本概念 資料抽象 繼承和動態繫結。在 c 中,用類進行資料抽象,用類派生從乙個類繼承另乙個 派生類繼承基類的成員。動態繫結使編譯器能夠在執行時決定是使用基類中定義的函式還是派生類中定義的函式。15.1.物件導向程式設計 概述 1 物件導向程式設計的關鍵思想是多型性 po...
c primer閱讀筆記 15章 5
15.5.繼承情況下的類作用域 1 在繼承情況下,派生類的作用域巢狀在基類作用域中。如果不能在派生類作用域中確定名字,就在外圍基類作用域中查詢該名字的定義。正是這種類作用域的層次巢狀使我們能夠直接訪問基類的成員,就好象這些成員是派生類成員一樣。15.5.1.名字查詢在編譯時發生 1 物件 引用或指標...
c primer閱讀筆記 15章 7
15.8.控制代碼類與繼承 1 c 中物件導向程式設計的乙個頗具諷刺意味的地方是,不能使用物件支援物件導向程式設計,相反,必須使用指標或引用。2 但是,使用指標或引用會加重類使用者的負擔。3 c 中乙個通用的技術是定義包裝 cover 類或控制代碼類。控制代碼類儲存和管理基類指標。指標所指物件的型別...