原文 from www.learncpp.com/cpp-tutorial/88-constructors-part-ii/
私有構(gòu)造函數(shù)
偶爾,我們不想讓用戶(hù)在class外使用特殊的構(gòu)造函數(shù)。為了實(shí)現(xiàn)這個(gè)想法,我們可以將構(gòu)造函數(shù)設(shè)定為私有的。
1: class Book
2: {
3: private:
4: int m_nPages;
5:
6: // This constructor can only be used by Book's members
7: Book() // private default constructor
8: {
9: m_nPages = 0;
10: }
11:
12: public:
13: // This constructor can be used by anybody
14: Book(int nPages) // public non-default constructor
15: {
16: m_nPages = nPages;
17: }
18: };
19:
20: int main()
21: {
22: Book cMyBook; // fails because default constructor Book() is private
23: Book cMyOtherBook(242); // okay because Book(int) is public
24:
25: return 0;
26: }
public的構(gòu)造函數(shù)具有的一個(gè)問(wèn)題是它們沒(méi)有提供任何控制一個(gè)特殊的類(lèi)能夠被創(chuàng)建多少次的方法。如果一個(gè)public構(gòu)造函數(shù)存在,就能夠人用戶(hù)的愿望實(shí)例化足夠多的類(lèi)對(duì)象。通常限制用戶(hù)只能夠?qū)嵗粋€(gè)特殊的類(lèi)是有用的。有很多方式實(shí)現(xiàn)單例(singletons),最常用的是使用私有或保護(hù)的構(gòu)造函數(shù)。
Constructor chaining and initialization issues
當(dāng)你實(shí)例化一個(gè)新的對(duì)象的時(shí)候,對(duì)象構(gòu)造函數(shù)被編譯器隱式調(diào)用。有兩個(gè)狀況可能是新手經(jīng)常犯錯(cuò)的地方:
1)有時(shí)候,一個(gè)類(lèi)具有一個(gè)能夠做另一個(gè)構(gòu)造函數(shù)相同工作的構(gòu)造函數(shù),并增加額外的工作。處理器讓一個(gè)構(gòu)造函數(shù)調(diào)用另一個(gè)構(gòu)造函數(shù),叫做constructor chaining。如果你嘗試這樣做,它能夠通過(guò)編譯,但是它將不能夠正確的工作,然后你就得花費(fèi)大量的時(shí)間去找出原因,甚至使用debugger。但是,構(gòu)造函數(shù)允許調(diào)用非構(gòu)造函數(shù)。通常要小心,使用已經(jīng)初始化的變量。
(譯者加:這里C++中為什么不能使用constructor chaining呢,可以跟蹤一下下面這段代碼答案就出來(lái)了:
1: #include <iostream>
2: using namespace std;
3:
4: class Foo
5: {
6: int m_nValue;
7: public:
8: Foo() { m_nValue = 1; }
9:
10: // 這里沒(méi)用到a,因?yàn)橹皇且粋€(gè)示例
11: Foo(int a) { Foo(); }
12:
13: ~Foo() { cout << "destructed" << endl; }
14:
15: int getValue() { return m_nValue; }
16: };
17:
18: int main()
19: {
20: Foo cTmp(1);
21: cout << cTmp.getValue1();
22: }
)
盡管你能將一個(gè)構(gòu)造函數(shù)中的代碼復(fù)制到另一個(gè)構(gòu)造函數(shù)中,重復(fù)性的代碼會(huì)使得你的類(lèi)變得臃腫。最好的解決方法是創(chuàng)建一個(gè)非構(gòu)造函數(shù)實(shí)現(xiàn)公共的初始化。
1: class Foo
2: {
3: public:
4: Foo()
5: {
6: // code to do A
7: }
8:
9: Foo(int nValue)
10: {
11: // code to do A
12: // code to do B
13: }
14: };
變?yōu)?/p>
1: class Foo
2: {
3: public:
4: Foo()
5: {
6: DoA();
7: }
8:
9: Foo(int nValue)
10: {
11: DoA();
12: // code to do B
13: }
14:
15: void DoA()
16: {
17: // code to do A
18: }
19: };
2)也許你想要一個(gè)成員函數(shù)實(shí)現(xiàn)將成員變量設(shè)定為默認(rèn)值。因?yàn)槟憧赡芤呀?jīng)通過(guò)構(gòu)造函數(shù)實(shí)現(xiàn)了,你也許會(huì)在成員函數(shù)中調(diào)用構(gòu)造函數(shù)。但是這在C++中是不合法的。
類(lèi)似1)中實(shí)現(xiàn)的方式
1: class Foo
2: {
3: public:
4: Foo()
5: {
6: Init();
7: }
8:
9: Foo(int nValue)
10: {
11: Init();
12: // do something with nValue
13: }
14:
15: void Init()
16: {
17: // code to init Foo
18: }
19: };
如果Init中有動(dòng)態(tài)分配內(nèi)存的情況,需要更加小心的對(duì)待了。在執(zhí)行相應(yīng)的操作之前,應(yīng)該進(jìn)行一定的檢測(cè)。避免錯(cuò)誤的發(fā)生。