關於C++的建構函式, 複製建構函式 和 operator =
1.建構函式
建構函式的定義我就不說了,我想說的只有一點,看下面的例子:
class C1
{
public:
//資料成員
int m_n;
//建構函式
C1(int n = 0)
{
cout << "C1::C1()" << endl;
m_n = n;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
C1 o(10);//1.調用建構函式
C1 o1 = 10;//2.同樣可以通過編譯,也是調用了建構函式
C1 o2;//3
o2 = 10;//4.調用建構函式,生產臨時對象,再賦值給o2
return 0;
}
標1的地方很容易理解,直接調用建構函式,把10作為參數傳遞,但標2的地方多少有點費解了.把一個int 賦值給C1對象o2嗎?不!看是一個賦值(=)實際上是初始化,也會調用建構函式(前提是存在適當形式的建構函式,比如上面,只有一個int參數,而=號右邊的10也是一個int);
標4的地方同樣調用了建構函式,把10傳遞給了建構函式,生產了一個臨時對象,然後把這個臨時對象賦值給了o2(這裡要調用 operator =(),如果有的話)
不過看起來似乎有點彆扭,我聲明了一個C1的對象o1,卻給了它一個int型的初始值.並且有時候這樣的"轉換"是危險的,需要避免(比如STL裡面就有許多這樣的例子),那就需要explicit關鍵字:
把建構函式改為這樣:
//建構函式
explicit C1(int n = 0)
{
cout << "C1::C1()" << endl;
m_n = n;
}
再去編譯上面的代碼,編譯器就會報錯了.我們成功阻止了不受歡迎的轉換.
2.複製建構函式
複製建構函式的原型是這樣的:
T(const T& src)
具體到上面的類就是
//複製建構函式
C1(const C1& src)
{
cout << "Copy constructor" << endl;
m_n = src.m_n;
}
當然,這個類很簡單,實際上根本不用再定義複製建構函式,系統預設的bitwise copy就夠了.
//一個函數,返回C1類型
C1 f1()
{
C1 cTemp(10);//*
return cTemp;
}
int _tmain(int argc, _TCHAR* argv[])
{
C1 n = f1();//這裡就是調用了複製建構函式
return 0;
}
注意:這個過程分別調用了一次建構函式(標*的地方),一次複製建構函式,如果把f1()裡面改為:
return C1(10);
的話,就可以節省一次複製建構函式的調用了(相當於直接定義 C1 n(10)).
3.operator =
這個就比較簡單了
C1& operator = (const C1& r)
{
if(&r == this) return *this;//防止自身賦值
m_n = r.m_n;
return *this;//支援連續賦值
}
如果定義了這個成員函數,在進行如下賦值操作時,就會調用該函數:
n2 = n1;//n2,n1都是C1類型的對象
當然你還可以定義其他參數類型的operator =()函數,以支援把其他類型的對象賦值給C1的對象.
需要說明的是,
n2 = n1;//n2,n1都是C1類型的對象
調用的是operator = 而不是 賦值建構函式 !很多的初學者(包括我)一開始容易迷惑.