拷貝構造函數(shù)_第1頁
拷貝構造函數(shù)_第2頁
拷貝構造函數(shù)_第3頁
拷貝構造函數(shù)_第4頁
拷貝構造函數(shù)_第5頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、拷貝構造函數(shù)一.什么是拷貝構造函數(shù)首先對于普通類型的對象來說,它們之間的復制是很簡單的,例如:int a = 100;mt b = a;而類對象與普通對象不同,類對象內部結構一般較為復雜,存在各種成員變量。 下面看一個類對象拷貝的簡單例子。#iiiclude <iostreain>using namespace std;class CExample private:hit a;public:構造函數(shù)CExaniple(iiit b)a = b;一般函數(shù)void Show ()(cout«a«endl;mt mam()(CExaniple A(100);CExam

2、ple B = A; 注意這里的對象初始化要調用拷貝構造函數(shù),而非賦值B.Show ();return 0;運行程序,屏幕輸出100。從以上代碼的運行結果可以看出,系統(tǒng)為對象B分配 了內存并完成了與對象A的復制過程。就類對象而言,相同類型的類對象是通 過拷貝構造函數(shù)來完成整個復制過程的。下面舉例說明拷貝構造函數(shù)的工作過程。#iiiclude <iostreain> using namespace std;class CExample private:mt a;public:構造函數(shù)CExaniple(mt b)a = b;拷貝構造函數(shù)CExaniple(const CExainpl

3、e& C) (a = C.a;)一般函數(shù)void Show ()cout«a«endl;);mt mam()CExaniple A(100);CExaniple B = A; CExample B(A);也是一樣的B.Show ();return 0;)CExample(const CExample& C)就是我們自定義的拷貝構造函數(shù)??梢?,拷貝構 造函數(shù)是一種特殊的構造函數(shù),函數(shù)的名稱必須和類名稱一致,它必須的一個參 數(shù)是本類型的一個引用變量。二.拷貝構造函數(shù)的調用時機在C+中,下面三種對象需要調用拷貝構造函數(shù)!1.對象以值傳遞的方式傳入函數(shù)參數(shù)class

4、 CExample(private:mt a;public:構造函數(shù)CExample(mt b)a = b;cout«ncreat: H«a«endl;)拷貝構造CExample(const CExample& C) a = C.a;cout«ncopyH<<endl;)析構函數(shù)CExample。 cout« "delete: "«a«endl;)void Show ()cout«a«endl: ;全局函數(shù),傳入的是對象void g_Fun(CExample C)

5、(cout«"test"«endl; hit(CExample test(l);傳入對象g,Fun(test);return 0;調用g_Fun()時,會產(chǎn)生以下幾個重要步驟:(1) . test對象傳入形參時,會先會產(chǎn)生一個臨時變量,就叫C吧。(2) .然后調用拷貝構造函數(shù)把test的值給C。整個這兩個步驟有點像:CExampleC(test); (3).等g_Fun()執(zhí)行完后,析構掉C對象。2.對象以值傳遞的方式從函數(shù)返class CExample private:mt a;public:構造函數(shù)CExample(iiit b)( a = b;)拷

6、貝構造CExample(const CExample& C) (a = C.a;cout«HcopyH«endl;)void Show (J( cout«a«endl;) ;全局函數(shù)CExample g_Fun() (CExample temp(O);return temp: hit mam()(g-Fun();return 0;當g_Fun()函數(shù)執(zhí)行到return時,會產(chǎn)生以下幾個重要步驟:(1) .先會產(chǎn)生一個臨時變量,就叫XXXX吧。(2) .然后調用拷貝構造函數(shù)把temp的值給XXXXo整個這兩個步驟有點像:CExample XXXX

7、(temp) ; (3).在函數(shù)執(zhí)行到最后先析構temp局部變量。(4) .等g_Fun ()執(zhí)行完后再析構掉XXXX對象。3 .對象需要通過另外一個對象進行初始化CExample A(100);CExample B = A;/ CExample B(A);后兩句都會調用拷貝構造函數(shù)。三.淺拷貝和深拷貝1 .默認拷貝構造函數(shù)很多時候在我們都不知道拷貝構造函數(shù)的情況下,傳遞對象給函數(shù)參數(shù)或者 函數(shù)返回對象都能很好的進行,這是因為編譯器會給我們自動產(chǎn)生一個拷貝構造 函數(shù),這就是“默認拷貝構造函數(shù)”,這個構造函數(shù)很簡單,僅僅使用“老對象” 的數(shù)據(jù)成員的值對“新對象”的數(shù)據(jù)成員一一進行賦值,它一般具有

8、以下形式:Rect:Rect(const Rect& r) (width = r.widtli;height = r.height;當然,以上代碼不用我們編寫,編譯器會為我們自動生成。但是如果認為這樣就 可以解決對象的復制問題,那就錯了,讓我們來考慮以下一段代碼:class Rect(public:Rect() 構造函數(shù),計數(shù)器加1(count+;-Rect() 析構函數(shù),計數(shù)器減1(count"static nit getC ount()/返回計數(shù)器的值(return count;private:mt width;mt height;static int count; /

9、一靜態(tài)成員做為計數(shù)器;mt Rect:count = 0;/初始化計數(shù)器mt mam()(Rect recti;cout«"The count of Rect: H«Rect: :getCount()«endl;Rectrect2(rectl); 使用recti狂制iect2,此時應該有兩個對象cout«nThe count of Rect: "«Rect: :getCouiitO«endl;return 0;這段代碼對前面的類,加入了一個靜態(tài)成員,目的是進行計數(shù)。在主函數(shù)中,首 先創(chuàng)建對象recti,輸出此時的對

10、象個數(shù),然后使用recti復制出對象rect2, 再輸出此時的對象個數(shù),按照理解,此時應該有兩個對象存在,但實際程序運行 時,輸出的都是1,反應出只有1個對象。此外,在銷毀對象時,由于會調用銷毀 兩個對象,類的析構函數(shù)會調用兩次,此時的計數(shù)器將變?yōu)樨摂?shù)。說白了,就是拷貝構造函數(shù)沒有處理靜態(tài)數(shù)據(jù)成員。出現(xiàn)這些問題最根本就在于在復制對象時,計數(shù)器沒有遞增,我們重新編寫拷貝 構造函數(shù),如下:class Rect(public:Rect() 構造函數(shù),計數(shù)器加1(COUllt-H-;Rect(const Rect& r) 拷貝構造函數(shù)(width = 1.width;height = r.he

11、iglit;couiit+;/計數(shù)器加1-Rect() 析構函數(shù),計數(shù)器減1(count;static int getC ount() /返回計數(shù)器的值(return count;private:mt width;mt height;static int count; / 一靜態(tài)成員做為計數(shù)器 ;2.淺拷貝所謂淺拷貝,指的是在對象復制時,只對對象中的數(shù)據(jù)成員進行簡單的賦值, 默認拷貝構造函數(shù)執(zhí)行的也是淺拷貝。大多情況下“淺拷貝”已經(jīng)能很好地工作 了,但是一旦對象存在了動態(tài)成員,那么淺拷貝就會出問題了,讓我們考慮如下 一段代碼: class Rect ( public:Rect() 構造函數(shù),p

12、指向堆中分配的一空間 ( p = new mt(100); Rect() 析構函數(shù),釋放動態(tài)分配的空間 ( if(p != NULL) delete p; private: mt width; mt height; mt *p;/ 一指針成員; mt mam() ( Rect recti; Rectrect2(rectl); / 亞制對象 return 0; 在這段代碼運行結束之前,會出現(xiàn)一個運行錯誤。原因就在于在進行對象復制時, 對于動態(tài)分配的內容沒有進行正確的操作。我們來分析一下:在運行定義recti對象后,由于在構造函數(shù)中有一個動態(tài)分配的語句,因此 執(zhí)行后的內存情況大致如下:在使用rec

13、ti復制rect2時,由于執(zhí)行的是淺拷貝,只是將成員的值進行賦 值,這時recti. p= rect2. p,也即這兩個指針指向了堆里的同一個空間,如下 圖所示:當然,這不是我們所期望的結果,在銷毀對象時,兩個對象的析構函數(shù)將對同一 個內存空間釋放兩次,這就是錯誤出現(xiàn)的原因。我們需要的不是兩個P有相同的 值,而是兩個P指向的空間有相同的值,解決辦法就是使用“深拷貝”。3.深拷貝在“深拷貝”的情況下,對于對象中動態(tài)成員,就不能僅僅簡單地賦值了, 而應該重新動態(tài)分配空間,如上面的例子就應該按照如下的方式進行處理:public:Rect() 構造函數(shù),p指向堆中分配的一空間 (p = new mt(

14、100);Rect(const Rect& r) (width = 1.width;height = r.heiglit;p = new mt; /為新對象重新動態(tài)分配空間*P = *&P);-Rect() 析構函數(shù),釋放動態(tài)分配的空間 (if(p != NULL) delete p; private:mt width;mt height;int *p;/ 一指針成員;此時,在完成對象的復制后,內存的一個大致情況如下:4防止默認拷貝發(fā)生通過對對象復制的分析,我們發(fā)現(xiàn)對象的復制大多在進行“值傳遞”時發(fā) 生,這里有一個小技巧可以防止按值傳遞一一聲明一個私有拷貝構造函數(shù)。甚至 不必去

15、定義這個拷貝構造函數(shù),這樣因為拷貝構造函數(shù)是私有的,如果用戶試圖 按值傳遞或函數(shù)返回該類對象,將得到一個編譯錯誤,從而可以避免按值傳遞或 返回對象。/防止按值傳遞class CExample(private:int a;public:構造函數(shù)CExaniple(iiit b)a = b;cout«Mcreat: n«a«endl;private:拷貝構造,只是聲明CExaniple(const CExample& C);public:CExample。(cout« "delete: "«a«endl;voi

16、d Show ()cout«a«endl;全局函數(shù)void g_Fun(CExample C)cout«"test"«endl;hit(CExaniple test(l);/g_Fun(test);按值傳遞將出錯return 0;I.拷貝構造函數(shù)的幾個細節(jié)1 .拷貝構造函數(shù)里能調用private成員變量嗎?解答:這個問題是在網(wǎng)上見的,當時一下子有點暈。其時從名子我們就知道拷貝 構造函數(shù)其時就是一個特殊的構造函數(shù),操作的還是自己類的成員變量,所以不 受private的限制。2 .以下函數(shù)哪個是拷貝構造函數(shù),為什么?X:X(constX&

17、amp;);X:X(X);X:X(X&, int a=l);X:X(X&, int a=l, mt b=2);解答:對于一個類x,如果一個構造函數(shù)的第一個參數(shù)是下列之一:a) X&b) const X&c) volatile X&d) const volatile X&且沒有其他參數(shù)或其他參數(shù)都有默認值,那么這個函數(shù)是拷貝構造函數(shù).X:X(const X&); 是拷貝構造函數(shù)X:X(X&,是拷貝構造函數(shù)X:X(X&, mt a=l, mt b=2); 當然也是拷貝構造函數(shù)3. 一個類中可以存在多于一個的拷貝構造函數(shù)嗎?解答:類中可以存在超過一個拷貝構造函數(shù)。class X public:X(con

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論