2016-04-22 66 views
2

這裏是我的問題的一個例子:爲什麼派生類的構造函數應該在其初始化列表中使用基類的默認構造函數?

class MyBaseClass 
{ 
public: 
    MyBaseClass(): my_bool(false), my_value(0) 
    {} 
    MyBaseClass(bool b, int i): my_bool(b), my_value(i) 
    {} 

private: 
    bool my_bool; 
    int my_value; 
} 

class MyDerivedClass1 : public ::MyBaseClass 
{ 
public: 
    MyDerivedClass1(double d): my_double(d) 
    {} 
private: 
    double my_double; 
} 

class MyDerivedClass2 : public ::MyBaseClass 
{ 
public: 
    MyDerivedClass2(double d): MyBaseClass(), my_double(d) 
    {} 
private: 
    double my_double; 
} 

爲什麼不是MyDerivedClass1初始化我的派生類與不必在MyDerivedClass2明確初始化基類像一個確定的呢?

我想我不明白爲什麼我不能只依靠C++調用我的基構造函數?我知道如果我想讓它們初始化爲不同的東西,我必須在初始化列表中調用另一個構造函數,但是我想要的只是要調用的基礎構造函數。

+0

你得到一個錯誤?如果您調用基構造函數,編譯器應自動調用基類的默認構造函數。 – NathanOliver

+0

@NathanOliver - 不,我沒有得到一個錯誤。我在代碼審查中被告知將基礎構造函數包含在MyDerivedClass2中,我問爲什麼。沒有人能給我一個很好的理由,缺少「文檔」。所以我在問爲什麼在這裏。另外,正如我在最佳實踐中谷歌週刊所說的那樣,調用基礎構造函數和我的同事選定這些原因,但我不知道爲什麼我應該在這種情況下。我希望有人有一個很好的理由。 – TWhite

+3

這聽起來像是一個編碼標準問題,在這種情況下,答案可能是沿着「它表明你已經考慮它並決定構建基礎的默認值是合適的,而不是忘記它」。 –

回答

4

在初始化程序列表中提供默認構造的基類或不提供它沒有區別。如果完全是你的風格,你會用什麼。 (或公司)

一般來說,假設你總是初始化你的成員,我會說你有2個選項(讓我們讓構造函數超出範圍)。

選項1:初始化init-list中的所有成員。

如果您與C++ 98兼容,則應使用此選項。它的優點是您可以將所有的施工參數定義在一個列表中,方便查找。 (除非你有50多個成員)

當你有多個構造函數時,這個選項的缺點是很多重複。

有了這個,你可以有3個變種爲他們:

  • 跳過默認的初始化類,這使得短名單,雖然這是很難檢查您是否打算「忘記」了。 (想想一個PTR給它更換類)
  • 默認初始化所有成員,這使得名單更長,但清楚地表明意圖
  • 明確規定要初始化類,通過複製與tempuary contructing

選項2:初始化所有成員的聲明,除了構造函數的參數

此選項假定您初始化類聲明的一切。再次,你可以明確地調用默認的構造函數或不使用,最好使用加載的init,因爲圓括號被解釋爲函數聲明。

在初始化程序列表中,您只需將與鏈接到構造參數的成員放在一起。

該選項的優點是可讀性(特別是對於大型類)。缺點是這會將您的編譯器選項限制爲「現代」編譯器。

基類

如果我們再考慮基類,看看他們,如果他們的成員,一致的辦法是明確地宣佈他們選擇1和不寫他們的選項2。

Personnally我喜歡選項2,因爲我經常遇到太多會員的班級,並且檢查是否所有會員都已經初始化,這一點很容易。

然而選項1經常被使用,因爲傳統爲了保持代碼的一致性。

POD

重要提的還有莢(普通老式的數據類型),如int,雙... 如果你不初始化他們,你得到一些隨機數據。無論您使用何種方法,這都明確地初始化它們非常重要。

結論

所以在最後,這一切都與一個沒有功能差異的風格問題。

2

儘管在大多數情況下沒有語義差異,並且問題主要是樣式之一,但是有一種情況是不同的:當基類的默認構造函數不是用戶提供的。

的差異來自於事實基礎,是不是在成員初始化列表是默認初始化,而明確地寫Base()值初始化它,執行零初始化,如果默認的構造函數ISN」用戶提供。

這樣:

struct A { int i; }; 
struct B : A { 
    B() : j(i) {} // may be undefined behavior 
    int j; 
}; 

struct C : A { 
    C() : A(), j(i) {} // OK; both i and j are zero 
    int j; 
}; 
+0

我會一直是零嗎?這個編譯器是否獨立? – TWhite

+0

我是否會被初始化?不是默認的構造函數跳過它嗎? – JVApen

相關問題