色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > C++中復(fù)制構(gòu)造函數(shù)與重載賦值操作符的深入分析

          C++中復(fù)制構(gòu)造函數(shù)與重載賦值操作符的深入分析

          作者: 時(shí)間:2016-12-01 來(lái)源:網(wǎng)絡(luò) 收藏
          C++++中復(fù)制控制是一個(gè)比較重要的話題,主要包括復(fù)制構(gòu)造函數(shù)、重載賦值操作符、析構(gòu)函數(shù)這三部分,這三個(gè)函數(shù)是一致的,如果需要手動(dòng)定義了其中了一個(gè),那么另外的兩個(gè)也需要定義,通常在存在指針或者前期相關(guān)操作的情況下,都需要手動(dòng)的定義。復(fù)制構(gòu)造函數(shù)與重載賦值操作符實(shí)現(xiàn)的大題相同,如果沒有手動(dòng)的實(shí)現(xiàn),那么編譯器會(huì)自動(dòng)生成一個(gè),而且這兩個(gè)函數(shù)的參數(shù)也是一致的,是不能夠改變的,這是為什么呢?這是值得我們?nèi)シ治龊屯魄玫?。析?gòu)函數(shù)相比前面的兩個(gè)存在一個(gè)巨大的差別,就是無(wú)論我們是否定義這個(gè)函數(shù),編譯器都會(huì)自動(dòng)生成一個(gè)析構(gòu)函數(shù)。析構(gòu)函數(shù)我認(rèn)為主要是完成對(duì)象的釋放操作,我就不去仔細(xì)的分析啦。


          我們現(xiàn)在著重來(lái)分析一下為什么復(fù)制構(gòu)造函數(shù)與重載賦值操作符在沒有定義的情況下,編譯器會(huì)為我們生成一個(gè),這說(shuō)明這兩個(gè)函數(shù)是一個(gè)類必不可少的部分。由此可知如果一個(gè)類沒有定義任何的東西,編譯器也會(huì)幫助我們生成下面的4個(gè)函數(shù):1、一個(gè)構(gòu)造函數(shù),也就是所謂的類名比如classname(),這是在沒有定義構(gòu)造函數(shù)時(shí),編譯器會(huì)自動(dòng)生成的。2、析構(gòu)函數(shù),這個(gè)前面已經(jīng)提到了。3、復(fù)制構(gòu)造函數(shù)。4、重載賦值操作符。

          為什么復(fù)制構(gòu)造函數(shù)和重載賦值操作符如此重要呢?

          首先介紹一下復(fù)制構(gòu)造函數(shù)與重載賦值操作符的聲明形式,這兩個(gè)函數(shù)的參數(shù)是固定的,是不能改變的。假設(shè)存在一個(gè)類Base。那么它的這兩個(gè)函數(shù)聲明分別如下所示:

          本文引用地址:http://cafeforensic.com/article/201612/324507.htm

          class Base
          {
          public:
          //構(gòu)造函數(shù)
          Base();
          //復(fù)制構(gòu)造函數(shù)
          Base(const Base &);
          //重載賦值操作符
          Base &operator=(const Base &);
          //析構(gòu)函數(shù)
          ~Base();
          ...
          private:
          ...
          };

          面的形式可以知道,復(fù)制構(gòu)造函數(shù)與重載賦值操作符的參數(shù)是一致的,都是該類的const引用類型。為什么不能重載呢?這些都是存在的問(wèn)題。我覺得要搞清楚這些問(wèn)題,首先我們就不能只能片面的去理解,而是應(yīng)該對(duì)C++的面向?qū)ο缶幊逃辛艘粋€(gè)較好的理解以后再來(lái)分析這個(gè)問(wèn)題。

          么是引用,很多書上都會(huì)說(shuō)是為了避免復(fù)制,這是其中的一個(gè)原因,如果說(shuō)只是這個(gè)原因,完全可以只用指針就可以了,對(duì)于系統(tǒng)而言,不在乎多幾個(gè)指針的存儲(chǔ)空間。
          首先說(shuō)明一下在C++中的繼承問(wèn)題,一般而言我們的繼承主要是指公共繼承,也就說(shuō)如下的派生類定義所示:

          class Derived : public Base
          {
          public:
          ...
          private:
          ...
          }

          公共繼承而言,基類的公共部分成為了派生類的公共部分,私有部分成為了派生類的私有部分。也就是說(shuō)派生類中包含基類的部分。也就是說(shuō)在實(shí)現(xiàn)派生類的過(guò)程中,基類的公用接口會(huì)被派生類直接繼承。而基類的私有成員也作為派生類的私有成員。但是對(duì)于其他的繼承類型,我就不去討論啦。這時(shí)派生類的成員可以訪問(wèn)到基類的私有成員。也就是說(shuō)相當(dāng)于派生類是在基類的基礎(chǔ)上增加了自己的特色。

          需要介紹一個(gè)問(wèn)題就是采用派生類對(duì)象的引用初始化基類的引用。多態(tài)性的動(dòng)態(tài)綁定中存在兩個(gè)條件:1、必須是virtual函數(shù)(虛函數(shù)),2、必須是通過(guò)基類的引用或者基類的指針進(jìn)行成員虛函數(shù)的調(diào)用。
          只有上面兩個(gè)條件滿足才能發(fā)生動(dòng)態(tài)調(diào)用問(wèn)題。

          由于派生類中存在基類的成員,也就相當(dāng)于一個(gè)派生類對(duì)象中包含了一個(gè)基類對(duì)象(我不知道這樣是否合理),所以可以采用一個(gè)基類引用來(lái)綁定一個(gè)派生類對(duì)象。引用實(shí)質(zhì)上是針對(duì)一塊內(nèi)存區(qū)域,引用是一個(gè)標(biāo)號(hào),是這塊內(nèi)存區(qū)域的一個(gè)名字,一個(gè)引用與一塊內(nèi)存區(qū)域綁定,因?yàn)榕缮鷮?duì)象中存在基類部分,可以認(rèn)為派生對(duì)象的區(qū)域中存在基類對(duì)象,這時(shí)可用基類的引用來(lái)表明這塊內(nèi)存區(qū)域,即采用一個(gè)基類的別名來(lái)表示(綁定)這段內(nèi)存區(qū)域,派生對(duì)象的地址(這段內(nèi)存)以及內(nèi)容都沒有發(fā)生改變,也沒有重現(xiàn)創(chuàng)造出一個(gè)新的對(duì)象,基類的引用還是指向這個(gè)派生對(duì)象。對(duì)于指針的分析方式相似。因此可以采用基類的引用綁定派生類對(duì)象。

          但是如何實(shí)現(xiàn)派生類對(duì)象到基類的轉(zhuǎn)換呢?
          這時(shí)候的轉(zhuǎn)換與前面的綁定存在很大的差別,因?yàn)檫@是重新分配一個(gè)基類對(duì)象,而不再是引用問(wèn)題,不再是綁定問(wèn)題,是依據(jù)一個(gè)派生類對(duì)象生成一個(gè)新的基類對(duì)象。因?yàn)榕缮悓?duì)象中存在一個(gè)基類對(duì)象基本的信息,完全可以生成一個(gè)基類對(duì)象,完全將此過(guò)程看作是一個(gè)初始化或者賦值的問(wèn)題。也就是采用派生類創(chuàng)建一個(gè)新的對(duì)象或者賦值一個(gè)對(duì)象。
          從上面的分析我們可以采用下面的形式來(lái)實(shí)現(xiàn):

          Base(const Derived &);
          Base &operator=(const Derived &);

          是在基類函數(shù)中采用構(gòu)造函數(shù)基于派生類來(lái)重載一系列的構(gòu)造函數(shù),但是這也存在一個(gè)問(wèn)題,如果存在很多派生類,這時(shí)候就要重載很多構(gòu)造函數(shù),這肯定不是我們需要的。

          這時(shí)候是否發(fā)現(xiàn)與前面的問(wèn)題關(guān)聯(lián)起來(lái)了?
          這時(shí)候我們發(fā)現(xiàn)對(duì)于一個(gè)類而言,為什么復(fù)制構(gòu)造函數(shù)和重載賦值操作符這么重要了。因?yàn)檫@兩個(gè)函數(shù)都是接受一個(gè)基類的引用,根據(jù)前面的分析我們知道一個(gè)基類引用完全可以綁定一個(gè)派生類的對(duì)象,而派生類對(duì)象中又包含了一個(gè)基類對(duì)象的基本信息。我們能夠?qū)崿F(xiàn)一個(gè)從一個(gè)派生對(duì)象到基類的構(gòu)造過(guò)程。
          我們用一個(gè)基類引用綁定一個(gè)派生對(duì)象,然后采用基類引用對(duì)基類成員進(jìn)行訪問(wèn),完成了一個(gè)基類對(duì)象基本要素的填充操作,相當(dāng)于完成了基類對(duì)象的創(chuàng)建,也就是構(gòu)造問(wèn)題。這樣也就能完成由派生類對(duì)象到基類對(duì)象的構(gòu)造過(guò)程。
          至于為什么是一個(gè)const的引用,我認(rèn)為主要是因?yàn)椴蝗バ薷呐缮悓?duì)象和擴(kuò)大能夠接受的參數(shù)情況,由const引用可以綁定不同類型的對(duì)象特性,說(shuō)明const引用會(huì)擴(kuò)大接受實(shí)參的能力。

          現(xiàn)在我可以總結(jié)起來(lái)說(shuō)了,因?yàn)樵趶?fù)制構(gòu)造函數(shù)中,C++中的基類引用可以綁定一個(gè)派生類的對(duì)象,如果在允許訪問(wèn)的情況下,采用基類引用可以訪問(wèn)基類的成員以及派生類的其他成員,采用引用可以復(fù)制派生類對(duì)象中基類成員的值到新創(chuàng)建的基類成員中,完成一個(gè)基類成員數(shù)據(jù)的填充操作,這時(shí)候一個(gè)完整的基類對(duì)象就創(chuàng)建完成了。

          重載賦值操作符則是發(fā)生在使用一個(gè)派生對(duì)象來(lái)賦值一個(gè)基類對(duì)象時(shí),這時(shí)候也是const基類引用綁定一個(gè)派生類對(duì)象,然后復(fù)制對(duì)應(yīng)的基類成員到基類對(duì)象對(duì)于的成員中,完成一個(gè)基類對(duì)象成員的更新操作。

          來(lái)說(shuō),復(fù)制構(gòu)造函數(shù)不僅僅實(shí)現(xiàn)了同類型之間的初始化操作,同時(shí)也完成了采用一個(gè)派生類對(duì)象初始化一個(gè)基類對(duì)象的操作,重載賦值操作符實(shí)現(xiàn)了同類型之間的賦值操作,也完成了采用派生類對(duì)象賦值基類對(duì)象的操作。如果沒有這兩個(gè)函數(shù)的存在,也就不能完成派生類到基類的賦值和初始化操作。這也是為什么一定會(huì)存在這兩個(gè)函數(shù)的原因。



          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉