標籤:影響 出現 bsp 構造 建立 const unsigned 要求 過程
建構函式初始值列表
1. 建構函式的初始值有時必不可少
• 有時我們可以忽略資料成員初始化和賦值之間的差異,但並非總能這樣。如果成員時const或者是引用的話,必須將其初始化。類似的,當成員屬於某種類類型且該類沒有定義預設建構函式時,也必須將這個成員初始化。
例如:
1 class ConstRef2 {3 public:4 ConstRef(int ii);5 private:6 int i;7 const int ci;8 int &ri;9 };
和其他常量對象或者引用一樣,成員ci和ri都必須被初始化。因此,如果我們沒有為它們提供建構函式初始值的話將引發錯誤:
1 //錯誤:ci和ri必須初始化2 3 ConstRef::ConstRef(int ii)4 {5 //賦值6 i=ii; //正確7 ci=ii; //錯誤:不能給const賦值8 ri=i; //錯誤:ri沒有初始化9 }
隨著建構函式體一開始執行,初始化就完成了。我們初始化const或者參考型別的資料成員的唯一機會就是通過建構函式初始值,因此該建構函式的正確形式應該是:
ConstRef::ConstRef(int ii): i(ii),ci(ii),ri(i) {} //正確:顯式地初始化引用和const成員
如果成員時const、引用,或者屬於某種未提供預設建構函式的類類型,我們必須通過建構函式初始值列表為這些成員提供初值(因為如果進行賦值操作,首先要進行一次預設初始化,這樣要使用都類類型的預設建構函式)。
2. 成員初始化順序
• 成員的初始化順序與它們在類定義中的出現順序一致:第一個成員先把初始化,然後第二個,以此類推。建構函式初始值列表中初始值的前後位置關係不會影響實際的初始化順序。
• 一般來說,初始化的順序沒什麼特別要求。不過如果一個成員是用另一個成員來初始化的,那麼這兩個成員的初始化順序就很關鍵了。
舉個例子,考慮下面這個類:
class X{ int i; int j;public: X(int val):j(val),i(j) {} //未定義的,i在j之前被初始化};
在此例中,從建構函式的形式上來彷彿是先用val初始化了j,然後再用j初始化i。實際上,i先把初始化,因此這個初始值的效果是試圖使用未定義的j初始化i!
如果可能的話,最好用建構函式的參數作為成員的初始值,而盡量避免使用同一個對象的其他成員。這樣的好處是我們可以不必考慮成員的初始化順序。例如,X的建構函式如果寫成如下的形式效果會更好:
X(int val):j(val),i(val) {}
3. 預設實參和建構函式
//定義預設建構函式,令其與只接受一個string實參的構造函功能相同Sales_data() {}等價於Sales_data(string s=" "):bookNo(s) {}
當沒有給定實參,或者給定了一個string實參時,兩個版本的類建立了相同的對象。因為我們不提供實參也能調用上面含有一個參數的建構函式,所以該建構函式實際上為我們的類提供了預設建構函式。
• 如果一個建構函式為所有參數都提供了預設實參,則它實際上也定義了預設的建構函式。
委託建構函式
• C++11新標準擴充了建構函式初始值的功能,使得我們可以定義所謂的委託建構函式。一個委託建構函式使用它所屬類的其他建構函式執行它自己的初始化過程,或者說它把它自己的一些(或者全部)職責給了其他建構函式。
和其他建構函式一樣,一個委託建構函式也有一個成員初始值的列表和一個函數體。在委託建構函式內,成員初始值列表只有一個唯一的入口,就是類名本身。和其他成員初始值一樣,類名後面緊跟圓括弧括起來的參數列表,參數列表必須與類中另一個建構函式匹配。
舉個例子,我們使用委託建構函式重寫Sales_data類,重寫後的形式如下所示:
1 class Sales_data 2 { 3 public: 4 //非委託建構函式使用對應的實參初始化成員 5 Sales_data(string s,unsigned cnt,double price):bookNo(s),units_sold(cnt),revenue(cnt*price) {} 6 7 //其餘建構函式全都是委託給另一個建構函式 8 //如果要在類的外面定義建構函式,則初始值列表在定義時寫出,而不是在類內聲明時寫出,委託建構函式也是這樣,在定義時寫 9 10 Sales_data():Sales_data(" ",0,0) {}11 Sales_data(string s):Sales_data(s,0,0) {}12 Sales_data(istream &is):Sales_data() {read(is,*this);}13 14 //其他成員與之前的版本一致15 };
【C++ Primer 第七章】 建構函式再探、委託建構函式