《高質量C++/C程式設計指南》第9章:類的建構函式、解構函式與賦值函式
B::B(const A &a) : m_a(a) { … } | B::B(const A &a) { m_a = a; … } |
F::F(int x, int y) : m_x(x), m_y(y) { m_i = 0; m_j = 0; } | F::F(int x, int y) { m_x = x; m_y = y; m_i = 0; m_j = 0; } |
9.5 不要輕視拷貝建構函式與賦值函式
由於並非所有的物件都會使用拷貝建構函式和賦值函式,程式設計師可能對這兩個函式有些輕視。請先記住以下的警告,在閱讀正文時就會多心:
①本章開頭講過,如果不主動編寫拷貝建構函式和賦值函式,編譯器將以“位拷貝”的方式自動生成預設的函式。倘若類中含有指標變數,那麼這兩個預設的函式就隱含了錯誤。以類String的兩個物件a,b為例,假設a.m_data的內容為“hello”,b.m_data的內容為“world”。
現將a賦給b,預設賦值函式的“位拷貝”意味著執行b.m_data = a.m_data。這將造成三個錯誤:一是b.m_data原有的記憶體沒被釋放,造成記憶體洩露;二是b.m_data和a.m_data指向同一塊記憶體,a或b任何一方變動都會影響另一方;三是在物件被析構時,m_data被釋放了兩次。
②拷貝建構函式和賦值函式非常容易混淆,常導致錯寫、錯用。拷貝建構函式是在物件被建立時呼叫的,而賦值函式只能被已經存在了的物件呼叫。以下程式中,第三個語句和第四個語句很相似,你分得清楚哪個呼叫了拷貝建構函式,哪個呼叫了賦值函式嗎?
String a(“hello”);
String b(“world”);
String c = a; // 呼叫了拷貝建構函式,最好寫成 c(a);
c = b; // 呼叫了賦值函式
本例中第三個語句的風格較差,宜改寫成String c(a) 以區別於第四個語句.
9.6 示例:類String的拷貝建構函式與賦值函式
// 拷貝建構函式
String::String(const String &other)
{
// 允許操作other的私有成員m_data
int length = strlen(other.m_data);
m_data = new char[length+1];
strcpy(m_data, other.m_data);
}
// 賦值函式
String & String:operate =(const String &other)
{
// (1) 檢查自賦值
if(this == &other)
return *this;
// (2) 釋放原有的記憶體資源
delete [] m_data;
// (3)分配新的記憶體資源,並複製內容
int length = strlen(other.m_data);
m_data = new char[length+1];
strcpy(m_data, other.m_data);
// (4)返回本物件的引用
return *this;
}
類String拷貝建構函式與普通建構函式(參見9.4節)的區別是:在函式入口處無需與NULL進行比較,這是因為“引用”不可能是NULL,而“指標”可以為NULL。
類String的賦值函式比建構函式複雜得多,分四步實現:
(1)第一步,檢查自賦值。你可能會認為多此一舉,難道有人會愚蠢到寫出 a = a 這樣的自賦值語句!的確不會。但是間接的自賦值仍有可能出現,例如
// 內容自賦值Oo5
©達內科技論壇 -- 達內科技論壇 ;"-tI
b = a;DKUd(
©達內科技論壇 -- 達內科技論壇 :;W
…©達內科技論壇 -- 達內科技論壇 6
©達內科技論壇 -- 達內科技論壇 (Sn*>
c = b;V3,ed
©達內科技論壇 -- 達內科技論壇 3H*"nq
…©達內科技論壇 -- 達內科技論壇 "a/.I
©達內科技論壇 -- 達內科技論壇 xEJH=v
a = c; hXb"
©達內科技論壇 -- 達內科技論壇 I7
©達內科技論壇 -- 達內科技論壇 Hbz
// 地址自賦值U
©達內科技論壇 -- 達內科技論壇 $+j
b = &a;S
©達內科技論壇 -- 達內科技論壇 !
…©達內科技論壇 -- 達內科技論壇 6a
©達內科技論壇 -- 達內科技論壇 b:
a = *b;x+
©達內科技論壇 -- 達內科技論壇 XB)
©達內科技論壇 -- 達內科技論壇 Cx
©達內科技論壇 -- 達內科技論壇 (
也許有人會說:“即使出現自賦值,我也可以不理睬,大不了化點時間讓物件複製自己而已,反正不會出錯!”?.
©達內科技論壇 -- 達內科技論壇 q&OU
他真的說錯了。看看第二步的delete,自殺後還能複製自己嗎?所以,如果發現自賦值,應該馬上終止函式。注意不要將檢查自賦值的if語句a|
©達內科技論壇 -- 達內科技論壇 dN"
if(this == &other)o{K
©達內科技論壇 -- 達內科技論壇 hmTkl
錯寫成為d|D(<
©達內科技論壇 -- 達內科技論壇 pdly>
if( *this == other)!:/
©達內科技論壇 -- 達內科技論壇 FWZ-
(2)第二步,用delete釋放原有的記憶體資源。如果現在不釋放,以後就沒機會了,將造成記憶體洩露。Vh
©達內科技論壇 -- 達內科技論壇 l8]cz
(3)第三步,分配新的記憶體資源,並複製字串。注意函式strlen返回的是有效字串長度,不包含結束符‘/0’。函式strcpy則連‘/0’一起復制。t<
©達內科技論壇 -- 達內科技論壇 d<.r8u
(4)第四步,返回本物件的引用,目的是為了實現象 a = b = c 這樣的鏈式表達。注意不要將 return *this 錯寫成 return this 。那麼能否寫成return other 呢?效果不是一樣嗎?,[;1E
©達內科技論壇 -- 達內科技論壇 A&5jUu
不可以!因為我們不知道引數other的生命期。有可能other是個臨時物件,在賦值結束後它馬上消失,那麼return other返回的將是垃圾。T
wR
9.7 偷懶的辦法處理拷貝建構函式與賦值函式x
©達內科技論壇 -- 達內科技論壇 .y)#Wb
如果我們實在不想編寫拷貝建構函式和賦值函式,又不允許別人使用編譯器生成的預設函式,怎麼辦?GQ
©達內科技論壇 -- 達內科技論壇 LW>G.a
偷懶的辦法是:只需將拷貝建構函式和賦值函式宣告為私有函式,不用編寫程式碼。HWlv#R
©達內科技論壇 -- 達內科技論壇 [!M
例如:`V
©達內科技論壇 -- 達內科技論壇 BYKu
class Ae7a$M[
©達內科技論壇 -- 達內科技論壇 ]8bY
{ …q.1
©達內科技論壇 -- 達內科技論壇 I3{p%7
private:;{(K
©達內科技論壇 -- 達內科技論壇 F
A(const A &a); // 私有的拷貝建構函式<|782
©達內科技論壇 -- 達內科技論壇 6n ?
A & operate =(const A &a); // 私有的賦值函式m
©達內科技論壇 -- 達內科技論壇 ZLv"G
};sst
©達內科技論壇 -- 達內科技論壇 >>!UEp
©達內科技論壇 -- 達內科技論壇 m
©達內科技論壇 -- 達內科技論壇 +
如果有人試圖編寫如下程式:!9>:u
©達內科技論壇 -- 達內科技論壇 -Hk
A b(a); // 呼叫了私有的拷貝建構函式~,u
©達內科技論壇 -- 達內科技論壇 O,
b = a; // 呼叫了私有的賦值函式}eCWm
©達內科技論壇 -- 達內科技論壇 %
編譯器將指出錯誤,因為外界不可以操作A的私有函式。F
9.8 如何在派生類中實現類的基本函式~G@
©達內科技論壇 -- 達內科技論壇 BXA`N
基類的建構函式、解構函式、賦值函式都不能被派生類繼承。如果類之間存在繼承關係,在編寫上述基本函式時應注意以下事項:_8S
©達內科技論壇 -- 達內科技論壇 G&:;1
派生類的建構函式應在其初始化表裡呼叫基類的建構函式。.8Z5b
基類與派生類的解構函式應該為虛(即加virtual關鍵字)。例如
#include
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1476436
相關文章
- 高質量C++/C程式設計指南(第9章 類的建構函式、解構函式與賦值函式) (轉)C++C程式程式設計函式賦值
- C++中建構函式,拷貝建構函式和賦值函式的詳解C++函式賦值
- C++ 類建構函式和解構函式C++函式
- 高質量C++/C程式設計指南(第6章 函式設計) (轉)C++C程式程式設計函式
- C++ 建構函式和解構函式C++函式
- 建構函式與解構函式函式
- 高質量C++/C程式設計指南(第8章 C++函式的高階特性) (轉)C++C程式程式設計函式
- 【C++】類初探常量成員函式與建構函式初始值列表C++函式
- C++建構函式解構函式的執行過程C++函式
- C++語言之結構體、類、建構函式、拷貝建構函式C++結構體函式
- C/C++——建構函式、複製建構函式和解構函式的執行時刻C++函式
- 預設建構函式、引數化建構函式、複製建構函式、解構函式函式
- 【C++】建構函式C++函式
- C++建構函式C++函式
- 類的建構函式和解構函式函式
- c++建構函式詳解C++函式
- C++入門記-建構函式和解構函式C++函式
- [C++]顯示呼叫建構函式和解構函式C++函式
- C++ 禁用類的複製建構函式和賦值運算子C++函式賦值
- 高階函式與標籤函式,解構賦值與物件字面量的簡化學習函式賦值物件
- Effective c++(筆記) 中關於建構函式、解構函式以及賦值操作符的知識C++筆記函式賦值
- C++解構函式C++函式
- PHP筆記:建構函式與解構函式PHP筆記函式
- 關於建構函式與解構函式的分享函式
- c++建構函式詳解薦C++函式
- 【C++】初始化列表建構函式VS普通建構函式C++函式
- 虛解構函式(√)、純虛解構函式(√)、虛建構函式(X)函式
- C++:建構函式的分類和呼叫C++函式
- 建構函式,拷貝賦值函式的N種呼叫情況函式賦值
- JS 建構函式與類JS函式
- 迴圈單連結串列建構函式、解構函式C++實現函式C++
- C++複製建構函式C++函式
- 第4周課後實踐·閱讀程式-建構函式與解構函式(1)函式
- C++建構函式和解構函式呼叫虛擬函式時使用靜態聯編C++函式
- C++拷貝建構函式詳解C++函式
- C++ 拷貝建構函式詳解C++函式
- C++之類解構函式為什麼是虛擬函式C++函式
- C++ Daily 《3》----建構函式可否是虛擬函式C++AI函式