C++在類的構(gòu)造函數(shù)中,可以兩種方式初始化成員數(shù)據(jù)(data member)。1,在構(gòu)造函數(shù)的實(shí)現(xiàn)中,初始類的成員數(shù)據(jù)。諸如:
class point
{
private:
int x,y;
public:
point(int m=0,int n=0)
{
x=m;
y=n;
}
int GetX()
{
return x;
}
int GetY()
{
return y;
}
};
2,還可以定義初始化成員列表(Initializer list)來初始化成員數(shù)據(jù)(data member)。
改寫構(gòu)造函數(shù)如下:
point(int m=0,int n=0):x(m),y(n)
{
}
這樣咋一看沒有什么不同,確實(shí),對(duì)于上面的這種簡(jiǎn)單列子來說,也真的沒有太大不同。
那我們?yōu)槭裁匆贸跏蓟蓡T列表,什么時(shí)候用初始化成員列表來初始化成員數(shù)據(jù)呢?Lippman的《C++ Primer》中提到在以下三種情況下需要使用初始化成員列表:
一,需要初始化的數(shù)據(jù)成員是對(duì)象的情況;
二,需要初始化const修飾的類成員;
三,需要初始化引用成員數(shù)據(jù);
現(xiàn)在分別舉例說明:
一,需要初始化的數(shù)據(jù)成員是對(duì)象。
---------------------------
#include <stdio.h>
class point
{
protected:
int m_x,m_y;
public:
point(int m=0,int n=0)
{
m_x = m;
m_y = n;
printf("constructor called!/n");
}
point(point& p)
{
m_x = p.GetX();
m_y = p.GetY();
printf("copy constructor called!/n");
}
int GetX()
{
return m_x;
}
int GetY()
{
return m_y;
}
};
class point3d
{
private:
point m_p;
int m_z;
public:
point3d(point p, int k)
{
m_p = p; //這里是對(duì)m_p的賦值
m_z=k;
}
point3d(int i,int j, int k):m_p(i,j) // 相當(dāng)于 point m_p(i,j)這樣對(duì)m_p初始化
{
m_z=k;
}
void Print()
{
printf("%d,%d,%d /n",m_p.GetX(),m_p.GetY(),m_z);
}
};
---------------------------------------
上述代碼中Point3d是一個(gè)3D坐標(biāo),他有一個(gè)point的2D坐標(biāo)和一個(gè)成員組成。
我們現(xiàn)在想定義一個(gè)3D坐標(biāo)p3d,可以這樣實(shí)現(xiàn):
void main()
{
point p(1,2); //先定義一個(gè)2D坐標(biāo)
point3d p3d(p,3);
p3d.Print();
}
從point3d實(shí)現(xiàn)體可以看出,我們是通過對(duì)m_p進(jìn)行賦值,這樣不僅調(diào)用copy constructor產(chǎn)生
臨時(shí)對(duì)象而且是對(duì)m_p的一個(gè)賦值操作。
而如果使用成員初始化列表,我們則可以這樣:
void main()
{
point p(1,2);
point3d p3d(1,2,3);
p3d.Print();
}
p3d中的point型成員是通過調(diào)用初始化的方式構(gòu)建的。由于對(duì)象賦值比初始化要麻煩的多,因此也帶來的性能上的消耗。(可以參見Scott Meyers著《effective C++》條款12)。
這也是我們?cè)趯?duì)成員數(shù)據(jù)是對(duì)象成員的采用初始化列表進(jìn)行初始始化的主要原因。
二,需要初始化const修飾的類成員;
三,需要初始化引用成員數(shù)據(jù);
對(duì)于類成員是const修飾,或是引用類型的情況,是不允許賦值操作的,(顯然嘛,const就是防止被錯(cuò)誤賦值的,引用類型必須定義賦值在一起)因此只能用初始化列表對(duì)齊進(jìn)行初始化。
上面兩點(diǎn)比較好明白,可以用一個(gè)例子加以說明:
-------------------------------------
#include <stdio.h>
class base
{
private:
const int a;
int& b;
public:
// base(int m, int n)
// {
// a = m;
// b = n;
// }
base(int m, int n):a(m),b(n)
{}
};
void main()
{
base ba(1,2);
}
有時(shí)必須用帶有初始化列表的構(gòu)造函數(shù):
(1)成員類型是沒有默認(rèn)構(gòu)造函數(shù)的類。若沒有提供顯示初始化式,則編譯器隱式使用成員類型的默認(rèn)構(gòu)造函數(shù),若類沒有默認(rèn)構(gòu)造函數(shù),則編譯器嘗試使用默認(rèn)構(gòu)造函數(shù)將會(huì)失敗。
(2)const成員或引用類型的成員。因?yàn)閏onst對(duì)象或引用類型只能初始化,不能對(duì)他們賦值。
(3)在繼承里面,只有初始化列表可以構(gòu)造父類的private成員。