這個(gè)是我們組的每日一例,主要目的是想通過(guò)老隊(duì)員指導(dǎo)新隊(duì)員,同時(shí)又可以鞏固大家的cpp知識(shí)。我們組長(zhǎng)說(shuō),項(xiàng)目做完之后這些東東可以整理出書(shū)了~
    這一份是我寫(xiě)的,所以就發(fā)布出來(lái)啦!~這個(gè)還算寫(xiě)得比較詳細(xì)吧!
 

Chapter One - 調(diào)用構(gòu)造函數(shù)對(duì)成員變量進(jìn)行構(gòu)造、初始化
 
    在類(lèi)構(gòu)造的時(shí)候,對(duì)于類(lèi)成員變量的構(gòu)造貌似可以在構(gòu)造函數(shù)中完成,那為什么還需要成員初始化表呢?
    我們來(lái)看看這樣的情況:
 
 1 /* programme 1 */
 2 class Base
 3 {
 4 public:
 5     Base(int val)
 6     : i(val) //這里為什么要放在成員初始化表呢?
 7     {
 8      //i = val??
 9     }
10     ~Base(){}
11 
12 private:
13     int i;
14 };
15 
16 class UseBase
17 {
18     Base b;
19 public:
20     UseBase(){} //沒(méi)有用Base的構(gòu)造函數(shù)
21     ~UseBase(){}
22 };
23 
24 int main()
25 {
26     return 0;
27 };
28 /* end of programme 1 */

    程序出現(xiàn)這樣的錯(cuò)誤:error C2512: 'Base' : no appropriate default constructor available,在UseBase中Base沒(méi)有被合理地初始化。
 
 1 /* programme 2 */
 2 
 3 //
 4 
 5 class UseBase
 6 {
 7     Base b;
 8 public:
 9     UseBase() : b(0){} //可以編譯通過(guò)
10     ~UseBase(){}
11 };
12 
13 //
14 
15 /* end of programme 2 */

 
    由此可以看出成員初始化列表的一個(gè)要點(diǎn),調(diào)用構(gòu)造函數(shù)對(duì)成員變量進(jìn)行構(gòu)造、初始化。對(duì)于內(nèi)置成員變量(int、double等等,個(gè)人理解為C語(yǔ)言中就已經(jīng)有的類(lèi)型,詳細(xì)信息參見(jiàn)Primer)而言沒(méi)有明顯的問(wèn)題,但對(duì)于非內(nèi)置成員變量而言,即便編程者沒(méi)有在成員初始化表中顯示調(diào)用構(gòu)造函數(shù),編譯器也會(huì)隱式地調(diào)用默認(rèn)構(gòu)造函數(shù)。所謂“默認(rèn)構(gòu)造函數(shù)”就是指"$classname$(void)"這樣的形式。上面的例子就是因?yàn)檫@個(gè)原因而編譯失敗的,Base沒(méi)有提供默認(rèn)構(gòu)造函數(shù)。也就是說(shuō),需要特殊構(gòu)造的類(lèi)必須在成員初始化列表進(jìn)行構(gòu)造、初始化。
 
    而如果有默認(rèn)構(gòu)造函數(shù),是否就可以在成員初始化表中置之不理呢?答案是否定的,這涉及到效率問(wèn)題。(以下程序可以中的Base完全可以用string類(lèi)型來(lái)取代,但為了方便調(diào)試方式查看,所以重新編寫(xiě)了Base。)
 
 1 /* programme 3 */
 2  
 3 class Base
 4 {
 5 public:
 6     Base(void)
 7     : i(0)
 8     {
 9     // breakpoint 1
10     }
11     // 賦值操作符重載
12     Base& operator= ( const int val )
13     {
14         i = val;// breakpoint 2
15         return *this;
16     }
17 
18     ~Base(){}
19 
20 private:
21     int i;
22 };
23 class UseBase
24 {
25     Base b;
26 public:
27     UseBase()
28     //: b(0)
29     {
30         b = 3;// breakpoint 3
31     }
32     ~UseBase(){}
33 };
34 
35 int main()
36 {
37     UseBase ub;
38     return 0;
39 };
40 /* end of programme 3 */

    breakpoint的順序?yàn)?-3-2,這說(shuō)明UseBase中的Base既進(jìn)行了默認(rèn)構(gòu)造,之后又進(jìn)行了賦值,原本可以通過(guò)一個(gè)構(gòu)造函數(shù)完成的操作,現(xiàn)在分成了兩個(gè)步驟,效率降低了。
 

Chapter Two - 派生類(lèi)的成員初始化表
 
    在派生類(lèi)的成員初始化表中,可以調(diào)用基類(lèi)的構(gòu)造函數(shù)來(lái)初始化其基類(lèi)成分。
 
 1 /* programme 4 */
 2 #include <iostream>
 3 using namespace std;
 4 class Base
 5 {
 6 public:
 7     Base( const int val )
 8     : i(val)
 9     {
10     }
11 
12     Base& operator= ( const int val )
13     {
14         i = val;
15         return *this;
16     }
17 
18     virtual ~Base(){}
19 
20     void print() const
21     {
22         cout << "val: " << i << endl;
23     }
24 
25 private:
26     int i;
27 };
28 
29 class Derived : public Base
30 {
31 public:
32     Derived( const int val )
33     : Base(val)
34     {}
35 };
36 
37 int main()
38 {
39     Derived d(1);
40     d.print();
41     getchar();
42     return 0;
43 };
44 /* end of programme 4 */

    一個(gè)小錯(cuò)誤,很多人可能會(huì)犯的:
 1 /* programme 5 */
 2 //
 3 
 4 class Derived : public Base
 5 {
 6 public:
 7     Derived( const int val )
 8     //: Base(val)
 9     {
10         Base(val);
11     }
12 };
13 
14 //
15 /* end of programme 5 */
 
    在構(gòu)造函數(shù)體內(nèi)直接調(diào)用基類(lèi)的構(gòu)造函數(shù),但這樣是不能完成對(duì)基類(lèi)成分的初始化的。這個(gè)語(yǔ)句的意義是創(chuàng)建一個(gè)臨時(shí)的Base對(duì)象。
 
 
Chapter Three - 初始化const、引用成員
 
    利用成員初始化表能夠初始化const、引用成員,這在構(gòu)造函數(shù)體內(nèi)是無(wú)法做到的。因?yàn)橐话闱闆r下,const、引用的對(duì)象在聲明的時(shí)候就要同時(shí)將值或?qū)ο蠼壎ǖ揭黄稹?br> 
 1 /* programme 6 */
 2 #include <iostream>
 3 #include <string>
 4 using namespace std;
 5 class dummy
 6 {
 7     const int ci;
 8     string& szStr;
 9 
10 public:
11     dummy(const int i, string &sz)
12     : ci(i)
13     , szStr(sz)
14     {}
15 
16     void printi()
17     {
18         cout << "const int: " << ci << endl;
19     }
20 
21     void printsz()
22     {
23         cout << "string&: " << szStr << endl;
24     }
25 
26     void setsz(string &sz)
27     {
28         szStr = sz;
29     }
30 };
31 
32 int main()
33 {
34     string _4ref("hello");
35     dummy d(10, _4ref);
36     d.printi();
37     d.printsz();
38     cout << endl;
39     d.setsz( string("goodbye") );
40     d.printsz();
41     cout << "_4ref: " << _4ref << endl;
42     getchar();
43     return 0;
44 };
45 /* end of programme 6 */

輸出結(jié)果
const int: 10
string&: hello

string&: goodbye
_4ref: goodbye