2010-11-24 200 views
1

讓例子是:基類的拷貝構造函數(C++)

class Base { 
    Base (const Base & copyFrom) { globalRegister (* this); } 
} 

class Derived { 
    Derived (const Derived & copyFrom) : Base (copyFrom) {} 
} 

我讀過的建議,包括初始化列表上的基地的拷貝構造函數的派生爲了複製Base的屬性(如示例中所示)。然而,我有基地的副本構造函數將自身(* this)傳遞給其他對象(用於註冊該對象)。如果實際上必須在Derived的複製構造函數的初始化列表中使用(隱式或顯式地)Base構造函數,並且僅在Derived的複製構造函數的主體中調用Base的複製構造函數時纔會出現這種情況,可以通過Base的拷貝構造函數來連接?否則 - (*這是)一個有效的對象?

+0

你沒有從`Base`的初始化列表中傳遞`* this`,對吧? – 2010-11-24 13:42:23

+0

@John Dibling:不,它在Base的拷貝構造函數的主體中。 – 2010-11-24 15:37:13

回答

4

請問這是哪裏我實際上必須使用(或明或暗地)基地的(默認)構造函數派生的拷貝構造函數的初始化列表中,並調用基的拷貝構造函數只有在派生的拷貝構造函數體的情況下,當實際上有一個對象可以被Base的拷貝構造函數連接時?

你爲什麼要這麼做?
(哦,你不能調用基類構造函數的身體從派生類拷貝構造函數只有從它的初始化列表。)

人 - 是(*此)有效的對象?

基地的初始化列表完成的那一刻,所有基地的成員(和基類)都被完全構建。然而,類本身只在構造函數完成時才被完全構造。
更重要的是,派生類的構造函數還沒有開始,所以對象還不是派生類的對象。

所以無論註冊功能如何,它必須考慮到對象的動態類型是base,並且其構造函數尚未完成。 (爲了安全起見,所有它能做的就是在一些地方保存對象的地址。)

1

僅供參考,行爲受§12.7 2-3 C++ 03規定:

2)爲了顯式或隱式地將指向類X的對象的指針(左值)轉換爲指向X的直接或間接基類B的指針(引用),構造X以及構造其所有直接或間接基類直接或間接從B派生的應該已經開始,並且這些類的銷燬不應該完成,否則轉換會導致未定義的行爲。

this是指向Derived的指針。在Base::Base()中,this隱式轉換爲Base*,由於Derived的構造已經啓動,並且沒有其他從Base派生的基礎,因此允許這樣做。

§12。7 2繼續:

爲了形成一個指針(或訪問的值)的對象物obj的直接非靜態成員,obj的結構應已經開始和它的破壞不得已完成,否則的計算指針值(或訪問成員值)導致未定義的行爲。

最後,§12.7 3也是很重要的:

3)成員函數,包括虛擬功能(10.3),可構造或破壞(12.6.2)中被調用。當從構造函數直接或間接地調用虛函數(包括來自數據成員的的mem初始化程序)或析構函數,並且該調用所應用的對象是正在構建或銷燬的對象時,調用的函數是在構造函數或析構函數自己的類中或在其基礎之一中定義的函數,但不是在派生於構造函數或析構函數類的類中重寫它的函數,或者在其他基類之一中覆蓋它的函數派生對象(1.8)。如果虛函數調用使用顯式類成員訪問(5.2.5),並且object-expression引用正在構建或銷燬的對象,但其類型既不是構造函數或析構函數自己的類或其基礎之一,調用未定義。

這兩個條款是指Derived一個實例是一個不折不扣的Base一次Base構造開始,儘管它可能是不一致的狀態。