2009-10-05 38 views

回答

5

默認構造函數是一個構造函數,它沒有參數,或者如果它有參數,所有參數都有默認值。

如果沒有用戶定義的構造存在的一類A和需要一個,編譯器隱式地聲明默認參數構造A :: A()。此構造函數是其類中的內聯公共成員。當編譯器使用此構造函數創建A類型的對象時,編譯器將隱含地定義A :: A()。構造函數將沒有構造函數初始值設定項和空實體。

在定義A的隱式聲明的構造函數之前,編譯器首先隱式定義了基類和非靜態數據成員的隱式聲明構造函數。沒有爲具有任何常量或引用類型成員的類創建默認構造函數。

* It is implicitly defined 
* A has no virtual functions and no virtual base classes 
* All the direct base classes of A have trivial constructors 
* The classes of all the nonstatic data members of A have trivial constructors 

如果以上都是假的,那麼構造器是平凡:

A類的構造函數,如果所有以下屬實實在是微不足道。

甲聯合成員不能是具有一個非平凡構造函數的類型。

像所有的功能,一個構造函數可以有默認參數。它們用於初始化成員對象。如果提供了默認值,則可以在構造函數的表達式列表中省略結尾參數。請注意,如果構造函數具有任何沒有默認值的參數,則它不是默認構造函數。

閱讀

Default constructors (C++ only)

+0

菲尼克斯,謝謝你回答上面的一些對我來說是新的:)...但我想知道在構造對象期間什麼是編譯器在完成對象創建之前所做的事情。你的答案是建造物體之後。 – mahesh

+1

雖然IBM的參考通常不錯,但不是一個好的定義: –

+0

這個構造函數是它的類的一個內聯公共成員即使這是真的(並且我需要從標準中引用一句話來說服我)它不是真正相關。 –

1

什麼是創建完整的對象之前

編譯器提供的默認構造函數將做以下是編譯器的東西:

  • 調用默認的構造函數基類(如果有基類)
  • 調用每個類的數據成員的默認構造函數(對於每個具有構造函數的數據成員,這意味着不是基本類型)...並且如果有異常由其中一個引發,然後調用任何以前創建的數據成員的析構函數。

「構造不是一個很普通的功能。特別是,在普通方式的成員函數不要與內存管理程序進行交互。」 :我正在尋找這種類型的答案..如果有人知道更多..請讓我知道嗎?:)

如果你這樣做......

Something* something = new Something(); 

...然後調用「new運算符」(和默認運算符new將分配從堆內存),然後調用構造函數在新分配的內存上。 Alteratively如果你這樣做:

Something something; 

...那麼分配(或保留)在堆棧上一些內存,然後調用對新分配的/預留的內存構造。

它與其他非靜態方法(包括析構函數)類似,事實上有一個「this」指針:不同之處在於,當構造函數被調用時,將包含「this」的內存剛被分配但還沒有初始化(這是構造函數的作用:它初始化「this」)。

+0

ChrisW,很好的回答...我想知道在產生默認構造函數的構造函數代碼中會發生什麼 – mahesh

+0

我不知道我是否已經回答/理解了您的問題。 – ChrisW

2

默認構造函數。

它具有零參數(或其所有參數都有默認值),因此可以構造一個沒有任何參數的對象。

如果您沒有定義任何構造函數,編譯器會爲您生成一個默認構造函數。
編譯器生成的默認構造函數(按以下順序)

  • 呼叫所有基類的默認構造(如果有的話,但在順序)。
  • 調用每個成員的默認構造函數(按它們在類中聲明的順序)。
    • 如果成員是int/float/char等,它是未定義的。
    • 如果該成員是一個指針,它是未定義的。

拷貝構造函數:

如果你沒有定義拷貝構造函數,則編譯器會生成一個默認的拷貝構造函數。
編譯器生成拷貝構造函數(按以下順序)

  • 調用所有基類的拷貝構造函數(如果有的話,但爲了)。
  • 調用每個成員的複製構造函數(按它們在類中聲明的順序)。
    • 每個成員都傳遞了被複制對象的相應成員。
    • 指針的注意事項這意味着只需複製指針值。
      這就是爲什麼當類包含對象管理的RAW指針時,我們會得到淺拷貝問題。

雖然不是一個構造函數。重要的是要注意,編譯器還會在未定義的時候自動生成賦值運算符。
編譯器生成的賦值運算符確實(按以下順序)

  • 呼叫每個基類的賦值運算符(如果有的話,但在順序)。
  • 調用每個成員的賦值運算符(按照它們在類中聲明的順序)。
    • 每個成員都傳遞了被複制對象的相應成員。
    • 指針的注意事項這意味着只需複製指針值。
      這就是爲什麼當類包含對象管理的RAW指針時,我們會得到淺拷貝問題。

默認的析構函數:
大多數人認爲的析構函數是平凡或不存在。但重要的是要注意默認版本實際上在做什麼(它稍微多於沒有)。

  • 每個成員都有其析構函數調用(在相反爲了申報)
  • 注意INT /浮點/指針不這麼沒有明確的做析構函數。
  • 每個基類析構函數都按相反順序調用。

如果您定義了析構函數,則行爲不會更改。但是你定義爲析構函數一部分的代碼是在上面定義的行爲之前執行的。所以在影響總是有一個析構函數,只是代碼是一個空的塊。

注意:使用虛擬基類時有一些特殊的考慮因素。但那是另一個問題。

所以即使你定義了一個空的類。編譯器總是生成四種方法你:

class X: public Z 
{ 
    int a; 
    Y b; 
    Z* c; 
}; 

// Compiler generated methods will look like this: 
X::X() 
    :Z() // Construct base class. 
    //,a?? The default construction of an int does nothing the value is undefined. 
    ,b() 
    //,c?? The default construction of a pointer does nothing, 
{} 
X::~X() 
{} // Note members are destoyed here 
    // ~c: Does nothing it is a pointer. 
    // ~b: destroyes b via Y::~Y() 
    // ~a: Does nothing as POD has not destructr. 
    // ~Z(): Destory base class. 
X::(X const& rhs) 
    :Z(rhs) 
    ,a(rhs.a) 
    ,b(rhs.b) 
    ,c(rhs.c) 
{} 
X& operator=(X const& rhs) 
{ 
    Z::operator=(rhs); 
    a = rhs.a; 
    b = rhs.b; 
    c = rhs.c; 
    return *this; 
} 
0

以下是我從Stroustrup的書

了「構造函數是不是一個很普通的功能 特別是,它與內存管理程序中進行交互普通會員功能 不會。「 :我正在尋找這種類型的答案..如果有人知道更多..請讓我知道嗎? :)

+0

我添加到我的答案,試圖回答這個問題。 – ChrisW

+0

馬丁·約克和ChrisW的答案都令人印象深刻。兩者皆爲+1。但我不能接受這兩個答案,我打算這麼做 – mahesh

相關問題