<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > C++中復制構造函數與重載賦值操作符的深入分析

C++中復制構造函數與重載賦值操作符的深入分析

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


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

為什么復制構造函數和重載賦值操作符如此重要呢?

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

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

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

面的形式可以知道,復制構造函數與重載賦值操作符的參數是一致的,都是該類(lèi)的const引用類(lèi)型。為什么不能重載呢?這些都是存在的問(wèn)題。我覺(jué)得要搞清楚這些問(wèn)題,首先我們就不能只能片面的去理解,而是應該對C++的面向對象編程有了一個(gè)較好的理解以后再來(lái)分析這個(gè)問(wèn)題。

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

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

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

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

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

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

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

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

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

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

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

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



評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>