1. 程式人生 > >類2(構造)

類2(構造)

花括號 自己的 blog data 添加 裏的 pre 實參 post

構造函數:

每個類都定義了它的對象被初始化的方式,類通過一個或幾個特殊的成員函數來控制其對象的初始化過程,這些函數叫做構造函數。構造函數的任務是初始化類對象的數據成員,無論何時只要類的對象被創建,就會執行構造函數。

構造函數的名字和類名相同。和其他函數不一樣的是,構造函數沒有返回類型。除此之外類似於其他的函數,構造函數也有一個(可能為空的)參數列表和一個(可能為空的)函數體。類可以包含多個構造函數,和其他重載函數差不多,不同的構造函數之間必須在參數數量或者參數類型上有所區別。

不同與其他成員函數,構造函數不能被聲明成 const 的,當我們創建類的一個 const 對象時,直到構造函數完成初始化過程,對象才能真正取得其 "常量" 屬性。因此,構造函數在 const 對象的構造過程中可以向其寫值。

合成的默認構造函數:

如果我們沒有顯示地定義構造函數,那麽編譯器就會隱式地定義一個默認構造函數(合成的默認構造函數)。一般情況下合成的構造函數按照如下規則初始化類的數據成員:

1.如果存在類內的初始值,用它來初始化成員

2.否則,默認初始化

合成的默認構造函數只適合非常簡單的類,比如上一篇博客中的 Sales_data 類。對於一般類來說是必須要定義默認構造函數的:

1.編譯器只有在發現類不包含任何構造函數的情況下才會生成一個默認的構造函數。一旦我們定義了一些其他的構造函數,那麽除非我們再定義一個默認的構造函數,否則類將沒有默認構造函數。

2.對於某些類來說,合成默認構造函數可能執行錯誤的操作。如果定義在塊中的內置類型或復合類型(比如數組和指針)的對象被默認初始化,則它們的值將是未定義的。這條準則同樣適用於默認初始化的內置類型成員。因此,含有內置類型或復合類型成員的類應該在類的內部初始化這些成員,或者定義一個自己的默認構造函數。否則,用戶在創建類的對象時就可能得到未定義的值。

3.有的時候編譯器不能為某些類合成默認的構造函數。如:如果類中包含一個其他類類型的成員且這個成員的類型沒有默認構造函數,那麽編譯器將無法初始化該成員。

現在我們來給上篇博客中的 Sales_data 類添加幾個構造函數:

 1 struct Sales_data{
 2     //數據成員
 3     std::string book_no;
 4     unsigned units_sold = 0;
 5     double revenue = 0.0;
 6 
 7     //新增的構造函數
 8     Sales_data() = default;//不接受任何實參,默認構造函數
 9
Sales_data(const std::string &s): book_no(s){}//除了book_no外其他成員將使用類內初始值 10 Sales_data(const std::string &s, unsigned n, double p): book_no(s), units_sold(n), revenue(p * n){} 11 Sales_data(std::istream); 12 13 //之前的函數成員 14 std::string isbn() const { 15 return book_no; 16 // return this->book_no;//等價語句 17 } 18 Sales_data& combine(const Sales_data&); 19 double avg_price() const; 20 };

首先我們定義了其他構造函數,如前面所述,編譯器不會再合成默認構造函數,所以我們通過 Sales_data() = default;顯示地定義了一個默認構造函數。在 c++11 標準中,如果我們需要默認的行為,那麽可以通過在參數列表後面寫上 = default;來要求編譯器生默認成構造函數。其中,= default 既可以和聲明一起出現在類的內部,也可以作為定義出現在類的外部。和其他函數一樣,如果 = default 在類內部,則默認構造函數是內聯的,反之則不是內聯的。(關於default:http://blog.csdn.net/a1875566250/article/details/40406883)

構造函數初始值列表:

1 Sales_data(const std::string &s): book_no(s){}//除了book_no外其他成員將使用類內初始值
2 Sales_data(const std::string &s, unsigned n, double p): book_no(s), units_sold(n), revenue(p * n){}

其中,和一般函數一樣,花括號裏面是函數體,不過這些構造函數唯一的目的就是為數據成員賦初值。不需要執行其他任務,所以函數體為空。冒號和花括號之間的是構造函數初始值列表,每個數據成員後面括號裏的就是該數據成員的初始值,不同成員的初始化通過逗號分隔開來。

在類外部定義構造函數:

1 Sales_data::Sales_data(std::istream &is){
2     read(is, *this);//read 函數的作用是從 is 中讀取一條信息然後存入 this 中
3 }

和其他定義在外部的成員函數一樣,我們需要用 :: 來指明該構造函數是哪個類的成員。

還需要註意的是該構造函數調用了 read 函數,所以該構造函數的定義必須寫在 read 函數的聲明之後。

類2(構造)