構造函數的名字和類的名字相同,沒有返回類型,在類的public域定義或聲明。
使用構造函數的三類方式:
1)顯示調用:e.g. Stock food = Stock("World Cabbage", 250, 1.25);
2)隱式調用:e.g. Stock garment("Furry Mason", 50, 2.5);
3)new:e.g. Stock *pstock = new Stock("Electric", 18, 19.0); //這種情況下,創建了一個沒有名字的Stock對象,將這個對象的地址賦給pstock,通過指針pstock使用這個對象。
默認構造函數:
默認構造函數沒有形參表。如果用戶沒有定義任何構造函數,編譯器會自動生成一個默認構造函數。但編譯器自動生成的默認構造函數不做任何事,e.g. Stock::Stock() {}。這樣帶來的結果就是, e.g. Stock st; st中的成員都未初始化。
如果用戶定義了任何構造函數,那編譯器就不會提供默認構造函數,用戶必須自己定義默認構造函數。如果用戶定義了帶形參的構造函數,但沒有定義默認構造函數,那如下的情況將會報錯:
Stock stock1; // Error, no default constructor
定義自己的默認構造函數有兩種方式:
1)隱式初始化:在默認構造函數體內對數據成員賦值。
e.g. Stock::Stock()
{ //在執行函數體之前,其實成員變量已經初始化過了,即company="", shares和share_value值未知
company = "no name";
shares = 0;
share_value = 0.0;
}
2)顯式初始化:在默認構造函數初始化列表中對數據成員初始化。
e.g. Stock::Stock: company(""),shares(0),share_value(0.0) {}
初始化列表只在構造函數的定義中而不是聲明中指定。
一般情況下,這兩種方式沒有差別,但2)效率更高,建議使用2)。
但有些情況下,只能使用2)來初始化數據成員。當類的成員中有const或引用類型成員以及沒有默認構造函數的類類型成員時,必須使用2)。因爲對於const成員或引用類型成員,只能初始化,不能對他們賦值;對於沒有默認構造函數的類類型成員,若採用1),則給它賦值之前其實它已經被創建,但因沒有默認構造函數,所以會創建失敗,因此也只能用2)初始化。
在使用2)時,成員被初始化的次序就是定義成員的次序,與初始化列表中的次序無關。
使用默認構造函數的幾種情況:
1) Stock first;//隱式調用默認構造函數
2) Stock first = Stock();//顯示調用默認構造函數
3) Stock *pst = new Stock;//隱式調用默認構造函數
4) Stock *pst1 = new Stock();//顯示調用默認構造函數
Stock second(); // 錯誤,這是聲明一個返回類型爲Stock的函數,不是聲明對象。
注意:內置或複合類型的成員的初始值依賴於對象的作用域:在局部作用域中這些成員不被初始化,而在全局作用域中它們被初始化。
e.g.
class base
{
private:
int a;
double b;
};
base A;//a=0,b=0.0
main()
{}
int a;
double b;
};
base A;//a=0,b=0.0
main()
{}
class base { private: int a; double b; }; main() { base B; //如果沒有default constructor,則a,b均未初始化,沒有初始值 }
int a; double b; }; main() { base B; //如果沒有default constructor,則a,b均未初始化,沒有初始值 }