(原創) 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。如以下範例
2#include <string>
3
4using namespace std;
5
6class Foo {
7public:
8 int getI() { return i; }
9 string getS(){ return s; }
10
11private:
12 int i;
13 string s;
14};
15
16int main() {
17 Foo foo;
18 cout << foo.getI() << endl;
19 cout << foo.getS() << endl;
20}
執行結果
我們發現以上程式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,會將程式用以下寫法:
2#include <string>
3
4using namespace std;
5
6class 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
19int 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。
所以完整的寫法如下
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
12using namespace std;
13
14class 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
27int main() {
28 Foo foo;
29 cout << foo.getI() << endl;
30 cout << foo.getS() << endl;
31}
執行結果
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