default constructor的迷思 (C/C++)

我們知道若不寫default constructor,compiler會幫我們產生一個synthesized default constructor,那到底我們還要不要自己寫default constructor呢?

首先澄清一個概念,default constructor定意為沒有參數的constructor,並非compiler自動產生的constructor,compiler自動產生的叫做synthesized default constructor(C++ Primer 4th P.458)。

當我們的class中沒有任何constructor時,compiler會自動幫我們產生synthesized defualt constructor。如以下範例

 1 #include  < iostream >
 2 #include  < string >
 3
 4 using   namespace  std;
 5
 6 class  Foo  {
 7public:
 8  int getI() return i; }
 9  string getS()return s; }
10
11private:
12  int i;
13  string s;
14}
;
15
16 int  main()  {
17  Foo foo;
18  cout << foo.getI() << endl;
19  cout << foo.getS() << endl;
20}

執行結果
- 858993460


我們發現以上程式compile沒問題,執行也沒問題,唯一遺憾的是getI()的private int i是個亂數,因為synthesized default Constructor只會對class中的class Type加以初始化,對於built-in type則不會初始化,所以int i還是亂數,但string s因為是library type,非built-in type,所以已經初始化成空字串。這告訴我們,若data member含有built-in type,就得自己寫default constructor。

若我們想提供一個參數的constructor,會將程式用以下寫法:

 1 #include  < iostream >
 2 #include  < string >
 3
 4 using   namespace  std;
 5
 6 class  Foo  {
 7public:
 8  Foo(int i) : i(i) {}
 9
10public:
11  int getI() return i; }
12  string getS()return s; }
13
14private:
15  int i;
16  string s;
17}
;
18
19 int  main()  {
20  Foo foo;
21  cout << foo.getI() << endl;
22  cout << foo.getS() << endl;
23}


(02/16/2007更新)compiler會給我們no appropriate default constructor available的錯誤訊息,也就是說,不寫其他constructor則已,一旦寫了其他的constructor,compiler就不會幫我們產生synthesized default constructor,若我們有用到default constructor,如20行的Foo foo,就一定要寫default constructor,否則連compiler這關都過不了。

(02/16/2007更新)哪些地方會用到default constructor呢?(C++ Primer 4th P.460)

1.若建立物件時,沒有提供參數將無法建立物件,因為class中有一個constructor後,compiler就不在自動產生synthesized default constructor了,也就是不能用Foo foo這種寫法,但這違背一般人寫程式的習慣。

2.靜態建立array時,需使用default constructor,如Foo fooa[3],除非改成Foo fooa[] = {1, 2, 3};寫法。

3.動態建立array時,需使用default construcor,如Foo *pfoo = new Foo[5];,若無default constructor,則以上寫法無法執行。

4.建立container時,若vector<Foo> foovec(3);寫法,一開始就得建立3個element,若無default constructor則無法執行。

基於以上理由,compiler會強制我們一定要寫default constructor。

所以完整的寫法如下

 1 /* 
 2(C) OOMusou 2007 http://oomusou.cnblogs.com
 3
 4Filename    : DefaultConstructorMyth.cpp
 5Compiler    : Visual C++ 8.0 / ISO C++
 6Description : Demo myth of Default Constructor
 7Release     : 01/03/2007 1.0
 8*/

 9 #include  < iostream >
10 #include  < string >
11
12 using   namespace  std;
13
14 class  Foo  {
15public:
16  Foo (int i = 0) : i(i) { }
17
18public:
19  int getI() return i; }
20  string getS()return s; }
21
22private:
23  int i;
24  string s;
25}
;
26
27 int  main()  {
28  Foo foo;
29  cout << foo.getI() << endl;
30  cout << foo.getS() << endl;
31}


執行結果

0


Conclusion
(02/15/2007新增)default constructor在C++重要的原因,在於對built-in type作初始化的動作,如int為0,double為0.0...,這些東西算是繼承自C語言的『歷史共業』,在C#/Java這些較新的語言中,default constructor的重要性就沒那麼大。

雖然有synthesized default constructor這個東西,但建議無論什麼時候,還是該寫自己的default constructor,就算只是foo() {}也好,這是一個值得鼓勵的coding style。

See Also
(原創) derived-class要怎麼呼叫base-class的constructor? (C/C++)
(原創) 為什麼derived-class會去執行base-class的default constructor? (C/C++)
(原創) 一個關於constructor的觀念問題 (C/C++) (Java) (C#) (.NET)

Reference
C++ Primer 4th section 12.4.3 p.458, p.460

你可能感兴趣的:(Constructor)