程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 合成的默認構造函數定義為delete的一種情況,構造函數delete

合成的默認構造函數定義為delete的一種情況,構造函數delete

編輯:C++入門知識

合成的默認構造函數定義為delete的一種情況,構造函數delete


1. 默認初始化

如果定義變量時沒有指定初值,則變量會被默認初始化,此時變量被賦予了“默認值”。

對於類類型的變量來說,初始化都是依靠構造函數來完成的。因此,即使定義某個類的變量(對象)時沒有提供初始化式,我們也能通過類的默認構造函數來完成初始化。即,“默認值”由默認構造函數來決定(前提是該類有默認構造函數)。

對於內置類型的變量來說,當定義沒有初始化式的變量時,系統有時會幫我們初始化變量。“默認值”由定義的位置決定:定義於任何函數體之外的變量被初始化為0;定義在函數體內部的變量默認值是未定義的,不會由系統自動初始化,雖然值是未定義的,但是仍然是有一個默認值的。即,“默認值”由定義的位置決定。

2. 針對const類型的默認值

const對象一旦創建後,其值就不能再改變,所以const對象必初始化(注意,必須由用戶來決定怎麼初始化從而給定默認值,而不是依靠系統)。

對於內置類型變量來說,我們自己初始化時,只有一種辦法,就是提供值。即const內置類型變量無法默認初始化,系統也不會提供默認值。因此類似以下的代碼語法上就是錯的:

const int ival;   // 錯誤,ival沒有初始化

對於類類型變量來說,我們通過構造函數來完成變量的初始化,這當然也包括了默認構造函數,因此可以在定義對象時,不提供初始化式:

const A object;   // 正確,通過默認構造函數來初始化

3. 合成的默認構造函數定義為delete的一種情況

1. 編譯器創建的合成的默認構造函數按以下規則初始化類的數據成員:

-> 如果該數據成員有類內初始值,則在默認構函數中用類內初始值來初始化成員。

-> 如果該數據成員沒有類內初始值,則在默認構造函數中該成員采取默認初始化。(更確切的說,是使用該成員的默認值)

2. 聯系《primer 5th》page450-451

-> 如果在類中,有一個沒有類內初始化器的const內置類型成員,則該成員沒有辦法初始化(因為const內置類型變量必須由用戶自己來初始化,注意:const的內置類型變量是無法默認初始化的)。因為該成員沒有辦法自己初始化(通過以上1的兩種方式初始化),因此該類的默認構造函數定義為刪除(delete)。

-> 如果在類中,有一個沒有類內初始化器的const類類型成員,且其類型沒有定義默認構造函數(導致該const類類型成員也沒有辦法默認初始化),因此該類的默認構造函數定義為刪除(delete)。

-> 如果在類中,有一個沒有類內初始化器的類類型成員,且其類型沒有定義默認構造函數(導致類類型成員也沒有辦法默認初始化),因此該類的默認構造函數被定義為刪除(delete)。

有關此處的delete情況小結:

1. 首先需要明確內置類型變量是否可以默認初始化取決於變量位置,但無論如何,對於非const內置類型變量而言,一定會有一個默認值,即便其也許是未定義的;而對於類類型變量,如果要有默認值,必須要有默認構造函數,如果沒有默認構造函數,其無法進行默認初始化。

2. 對於沒有類內初始化器的內置類型成員來說,const使成員失去了擁有默認值的能力。

3. 對於沒有類內初始化器的類類型成員來說,加不加const都一樣,因為其是否具有默認值的能力,是由該成員是否擁有默認構造函數進行默認初始化來決定的。


默認構造函數的定義

就是 類名 { }; 結束
默認構造函數  默認構造函數(default constructor)就是在沒有顯式提供初始化式時調用的構造函數。它由不帶參數的構造函數,或者為所有的形參提供默認實參的構造函數定義。如果定義某個類的變量時沒有提供初始化式就會使用默認構造函數。   如果用戶定義的類中沒有顯式的定義任何構造函數,編譯器就會自動為該類型生成默認構造函數,稱為合成的構造函數(synthesized default constructor)。   如果類包含內置或復合類型的成員,則該類就不應該依賴於合成的默認構造函數,它應該定義自己的構造函數來初始化這些成員。   C++編譯器必須為未聲明構造函數之class合成一個默認構造函數   第一,class 有member object(該member object有default constructor), class需要default constructor調用member object default constructor   第二,如果一個沒有任何constructor的class 派生自一個"帶有default constructor"的base class.那麼它的default constructor會被合成出來。   第三,如果一個class申明了virtual function,,如果該類沒有任何constructor,   編譯器也會為它加default constructor.   (如果用戶有constructor,編譯器會在他的constructor中添加一些code,用來初始化vptr)   第四,一個class(沒有申明任何constructor)派生自一個繼承串鏈,其中有一個或多個virtual base classes,編譯器也會合成出一個default constructor,在其中放入每一個virtual base class的執行期存取操作的的碼,   (如果用戶申明了constructors,編譯器會在constructor中安插virtual base class執行期存取操作的的碼)   上面四種分析合成出的default constructor都是nontrivial default constructors,   不在此情況之內的都trivial default constructors,它們實際上並不會被編譯器合成出來   在合成的default constructors,只有base class subobjects和member class object會   被初始化,所有其它的nonstatic data member,如整數、整數指針、整數數組等等都不會被編譯器初始化。
參考資料:baike.baidu.com/view/2785579.htm
 

C++ 為何有默認的構造函數又要自定義一個構造函數

默認構造函數只會初始化這個類,並不做多余的動作
自定義構造函數,可以對類體內變量進行賦值,也可以調用其他函數,比如:
class ball{
private:
float radius;
public:
void ball(float r){
radius=r;
cout<<"當前球體半徑為:"<<r<<endl;
}
}
當你定義一個ball的實體時可以這樣:
ball b1(2.5);
這時,b1的radius直接初始化為2.5,並且會在屏幕上打印:當前球體半徑為:2.5
這只是簡單的構造函數應用,你可以把他的能力加以擴展
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved