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

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

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

2、ple B = A; 注意這里的對(duì)象初始化要調(diào)用拷貝構(gòu)造函數(shù),而非賦值B.Show ();return 0;運(yùn)行程序,屏幕輸出100。從以上代碼的運(yùn)行結(jié)果可以看出,系統(tǒng)為對(duì)象B分配 了內(nèi)存并完成了與對(duì)象A的復(fù)制過(guò)程。就類對(duì)象而言,相同類型的類對(duì)象是通 過(guò)拷貝構(gòu)造函數(shù)來(lái)完成整個(gè)復(fù)制過(guò)程的。下面舉例說(shuō)明拷貝構(gòu)造函數(shù)的工作過(guò)程。#iiiclude <iostreain> using namespace std;class CExample private:mt a;public:構(gòu)造函數(shù)CExaniple(mt b)a = b;拷貝構(gòu)造函數(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)就是我們自定義的拷貝構(gòu)造函數(shù)??梢?jiàn),拷貝構(gòu) 造函數(shù)是一種特殊的構(gòu)造函數(shù),函數(shù)的名稱必須和類名稱一致,它必須的一個(gè)參 數(shù)是本類型的一個(gè)引用變量。二.拷貝構(gòu)造函數(shù)的調(diào)用時(shí)機(jī)在C+中,下面三種對(duì)象需要調(diào)用拷貝構(gòu)造函數(shù)!1.對(duì)象以值傳遞的方式傳入函數(shù)參數(shù)class

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

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

6、貝構(gòu)造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;當(dāng)g_Fun()函數(shù)執(zhí)行到return時(shí),會(huì)產(chǎn)生以下幾個(gè)重要步驟:(1) .先會(huì)產(chǎn)生一個(gè)臨時(shí)變量,就叫XXXX吧。(2) .然后調(diào)用拷貝構(gòu)造函數(shù)把temp的值給XXXXo整個(gè)這兩個(gè)步驟有點(diǎn)像:CExample XXXX

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

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

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

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

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

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

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

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

15、定義這個(gè)拷貝構(gòu)造函數(shù),這樣因?yàn)榭截悩?gòu)造函數(shù)是私有的,如果用戶試圖 按值傳遞或函數(shù)返回該類對(duì)象,將得到一個(gè)編譯錯(cuò)誤,從而可以避免按值傳遞或 返回對(duì)象。/防止按值傳遞class CExample(private:int a;public:構(gòu)造函數(shù)CExaniple(iiit b)a = b;cout«Mcreat: n«a«endl;private:拷貝構(gòu)造,只是聲明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);按值傳遞將出錯(cuò)return 0;I.拷貝構(gòu)造函數(shù)的幾個(gè)細(xì)節(jié)1 .拷貝構(gòu)造函數(shù)里能調(diào)用private成員變量嗎?解答:這個(gè)問(wèn)題是在網(wǎng)上見(jiàn)的,當(dāng)時(shí)一下子有點(diǎn)暈。其時(shí)從名子我們就知道拷貝 構(gòu)造函數(shù)其時(shí)就是一個(gè)特殊的構(gòu)造函數(shù),操作的還是自己類的成員變量,所以不 受private的限制。2 .以下函數(shù)哪個(gè)是拷貝構(gòu)造函數(shù),為什么?X:X(constX&

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

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論