最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

C++自制心得——類與對(duì)象中(拷貝構(gòu)造+賦值重載)

2023-09-06 13:11 作者:這年頭起名可真不容易  | 我要投稿

在開始我們今天的內(nèi)容之前,給大家介紹一個(gè)小東西,cout和cin,流插入流提取函數(shù)。

該函數(shù)的前置為頭文件iostream,并展開命名空間std,這兩個(gè)函數(shù)可替代printf,scanf的功能,而且使用體驗(yàn)比前者好得多。在這里左移操作符被重載為流插入函數(shù),右移操作符被重載為流提取函數(shù)(運(yùn)算符重載馬上就會(huì)講,不要著急),所以cin >> a的意思就是從控制臺(tái)提取對(duì)象賦給a,cout << a << endl的意思是把a(bǔ)的值打印在屏幕上并換行,先講這么多,運(yùn)算符重載會(huì)再講一點(diǎn),后續(xù)我會(huì)專門出一期iostream的專欄。

拷貝構(gòu)造函數(shù)

又是一段新代碼,讓我們看看它的運(yùn)行結(jié)果

哦豁,炸掉了,調(diào)試一下

噢,編譯器釋放了一個(gè)野指針,所以程序崩了。這里我們引入一個(gè)新概念,深淺拷貝。

淺拷貝就是值拷貝,你的值是什么,我的值就是什么,C語(yǔ)言用的就是淺拷貝,一般情況下沒(méi)有什么問(wèn)題,但在這里問(wèn)題很明顯

淺拷貝會(huì)導(dǎo)致兩個(gè)數(shù)組的指針指向同一塊空間,而在C++里析構(gòu)函數(shù)會(huì)在對(duì)象生命周期結(jié)束后自動(dòng)調(diào)用,因此對(duì)象s出了func作用域就會(huì)調(diào)用一次析構(gòu)函數(shù),導(dǎo)致對(duì)象s1的數(shù)組指針變?yōu)橐爸羔?,緊接著s1出作用域再次調(diào)用析構(gòu)函數(shù),導(dǎo)致程序崩潰。

深拷貝不僅僅是值拷貝,他還會(huì)拷貝整個(gè)數(shù)據(jù)的結(jié)構(gòu),正因如此,我們希望用深拷貝替代淺拷貝(對(duì)于復(fù)雜結(jié)構(gòu),淺拷貝基本沒(méi)有存在價(jià)值,引用比它好用得多),那有沒(méi)有辦法自動(dòng)進(jìn)行深拷貝?拷貝構(gòu)造函數(shù)與復(fù)制重載函數(shù)可以解決這個(gè)問(wèn)題,前者針對(duì)對(duì)象的初始化,后者針對(duì)對(duì)象的賦值。

我們先介紹拷貝構(gòu)造函數(shù)

拷貝構(gòu)造函數(shù)的幾個(gè)基本特點(diǎn)

1. k拷貝構(gòu)造函數(shù)只適用于對(duì)象的初始化,如果是對(duì)象的賦值,則不會(huì)調(diào)用構(gòu)造函數(shù)

2. 拷貝構(gòu)造函數(shù)函數(shù)名同構(gòu)造函數(shù),均為類名,構(gòu)成函數(shù)重載

3. 拷貝構(gòu)造函數(shù)形參不得出現(xiàn)該類的對(duì)象,這會(huì)導(dǎo)致死循環(huán)遞歸(有的編譯器會(huì)直接報(bào)錯(cuò))

我來(lái)解釋一下,Stack對(duì)象的傳參行為本質(zhì)上就是用已存在對(duì)象給目標(biāo)對(duì)象初始化,按照規(guī)則,我們需要調(diào)用拷貝構(gòu)造函數(shù),可如果那個(gè)函數(shù)就是拷貝構(gòu)造自身,拷貝構(gòu)造函數(shù)就會(huì)再次調(diào)用自身,陷入死循環(huán)

4. 構(gòu)造函數(shù)有多種調(diào)用方式

其余代碼同上

這三種調(diào)用方式均視為調(diào)用拷貝構(gòu)造函數(shù),注意Stack s3 = s2不會(huì)調(diào)用賦值重載函數(shù),因?yàn)楸举|(zhì)是初始化。

5. 如用戶未顯式定義,編譯器會(huì)生成構(gòu)造函數(shù),其有以下特點(diǎn),對(duì)內(nèi)置類型進(jìn)行淺拷貝,對(duì)自定義類型調(diào)用其構(gòu)造函數(shù)。

寫到這想起一件事情,記得給拷貝構(gòu)造加const,不要學(xué)我,容易被坑死。

6. 拷貝構(gòu)造函數(shù)也存在初始化列表,因?yàn)橐钥截悩?gòu)造形式初始化的對(duì)象不會(huì)調(diào)用構(gòu)造函數(shù),而是直接調(diào)用拷貝構(gòu)造函數(shù)

賦值重載函數(shù)

1. 運(yùn)算符重載

在C語(yǔ)言階段,我們一直缺乏一種直觀的方式來(lái)表達(dá)自定義類型的基本運(yùn)算,比方說(shuō)如果我們想寫一個(gè)日期+天數(shù),那我們就只能以函數(shù)調(diào)用的形式來(lái)完成相關(guān)計(jì)算。函數(shù)肯定是要寫的,不過(guò)我們能不能換一種表達(dá)形式,把函數(shù)調(diào)用的形式轉(zhuǎn)換為運(yùn)算符的形式,顯然,從代碼的易讀性和美觀性來(lái)講運(yùn)算符比傳統(tǒng)的函數(shù)調(diào)用好得多。C++提供了解決方案,就是運(yùn)算符重載。

date.h

date.cpp

把函數(shù)名換成operator加對(duì)應(yīng)重載運(yùn)算符就可以實(shí)現(xiàn)運(yùn)算符重載了

test.cpp

用法十分親民,一看就懂。

運(yùn)算符重載本質(zhì)上就是把運(yùn)算符作為函數(shù)使用,所以上面六個(gè)cout也可以這么寫

運(yùn)算符重載函數(shù)有如下特性:

1. 不可以用這種方式創(chuàng)造新運(yùn)算符(operator@就是非法函數(shù))

運(yùn)算符重載,顧名思義,意義的再次擴(kuò)展,顯然只有有意義的運(yùn)算符,才能重載。

2. 函數(shù)形參個(gè)數(shù)與運(yùn)算符操作數(shù)個(gè)數(shù)必須保持嚴(yán)格一致(自加自減除外,因?yàn)樵谧约幼詼p這一情景下,該規(guī)則與函數(shù)重載規(guī)則沖突,需要額外的占位形參解決問(wèn)題)

這是很自然的結(jié)論,比如“+”操作符需要兩個(gè)操作數(shù),你重載的“+”函數(shù)形參數(shù)目不對(duì)等,你能認(rèn)為你重載的函數(shù)在含義上與“+”保持一致嗎?

注:因?yàn)殡[含this指針的存在,成員函數(shù)的形參會(huì)少一個(gè)

3. 函數(shù)形參中必須包含自定義類型(內(nèi)置類型不用你再造一次輪子)

4. .*? ::? sizeof? ?:? .? 以上五個(gè)運(yùn)算符不能重載

運(yùn)算符重載用好了能做出什么效果?你覺(jué)得一個(gè)可以一鍵賦值,無(wú)元素上限的數(shù)組怎么樣。

test.h

slist.h

slist.cpp

通過(guò)對(duì)方括號(hào)運(yùn)算符的重載,再結(jié)合四大成員函數(shù),我們成功的把順序表改造成了數(shù)組,而這個(gè)新數(shù)組既擁有順序表的動(dòng)態(tài)擴(kuò)容能力,也保留了數(shù)組的靈活性。這個(gè)改造,可以說(shuō)相當(dāng)成功

接下來(lái),我以日期類為例給各位講解常用運(yùn)算符重載設(shè)計(jì)的一些技巧

date.h

date.cpp

這里有兩個(gè)地方看起來(lái)很奇怪,一個(gè)是友元函數(shù)(流插入流提取運(yùn)算符的重載函數(shù)),另一個(gè)就是某些成員函數(shù)后加的const,我們?cè)谙乱还?jié)會(huì)詳細(xì)講解這些,現(xiàn)在淺淺提一筆。

如果C++允許this指針在成員函數(shù)中顯式寫出,并允許有限修改,那我們就不需要寫這些補(bǔ)丁了。

第一個(gè),友元函數(shù),是為了解決Date的this指針不能換位的問(wèn)題。顯然,<<與>>的本質(zhì)還是函數(shù),而這兩個(gè)函數(shù)的具體功能分別在ostream類與istream類里實(shí)現(xiàn),所以套殼換皮的我們就要用到ostream與istream的對(duì)象,那么問(wèn)題就出現(xiàn)了,this指針一定占據(jù)形參的第一位,但是<<與>>運(yùn)算符在正常使用時(shí)的第一個(gè)參數(shù)不是日期類的this指針,而是庫(kù)類的對(duì)象。為了能夠正常使用該函數(shù),只能把它定義成全局。但定義成全局函數(shù),就必須要突破private限制,解決辦法有二,一是提供get函數(shù),二就是定義成友元函數(shù)

第二個(gè),懸空const,是為了解決Date的this指針不能正常被const修飾的問(wèn)題。const對(duì)象只能傳遞const this指針,顯然不能把它轉(zhuǎn)換成this,不然權(quán)限就要亂套了。但是this指針不能顯式寫出,我沒(méi)辦法給它加const修飾,只能懸空寫

1. 比較運(yùn)算符只需要寫>, ==或者<, ==函數(shù),剩下的四個(gè)都能代碼復(fù)用,我這里手寫了三個(gè)主要是為了滿足我的強(qiáng)迫癥。

2. +=與+,-=與-,這兩組只需要寫一個(gè),另一個(gè)就能代碼復(fù)用

3. 在2的情境下,我建議手搓前一個(gè)而不是后一個(gè),因?yàn)樾矢?/p>

以operator+為例,這個(gè)函數(shù)需要定義一個(gè)額外對(duì)象,并返回一個(gè)對(duì)象。那么對(duì)象tem調(diào)用一次拷貝構(gòu)造函數(shù),返回時(shí)構(gòu)造的臨時(shí)常變量再次調(diào)用拷貝構(gòu)造,合計(jì)兩次

但是operator+=的函數(shù)并不需要?jiǎng)?chuàng)建額外對(duì)象,也不需要返回對(duì)象,沒(méi)有構(gòu)造系函數(shù)帶來(lái)的空間與時(shí)間開銷

到這里,結(jié)論很明顯,令operator+調(diào)用operator+=相比用operator+=調(diào)用operator+效率更高。

4. 擁有占位符的operator++或--會(huì)被編譯器識(shí)別為后置++或--,而沒(méi)有占位符的會(huì)被識(shí)別為前置++或--,同樣的,前置++或--比后置++或--效率更高。

2. 賦值重載函數(shù)

operator=函數(shù)比較特別,與我們講的前三個(gè)成員函數(shù)長(zhǎng)得一點(diǎn)不像。

賦值重載函數(shù)具有如下特點(diǎn):

1. 只適用于對(duì)象間的賦值操作,因此也不具有初始化列表的功能

如果你的對(duì)象有某些成員不能賦值就不要用下面的法子拷貝

2. 作為默認(rèn)成員函數(shù),如未顯式定義將由編譯器隱式生成,隱式生成的函數(shù)對(duì)內(nèi)置類型完成淺拷貝,調(diào)用自定義類型的賦值重載函數(shù)

3. operator=作為雙目操作符,其重載函數(shù)必須擁有兩個(gè)形參(第一個(gè)給了this指針)

至于用法,operator=是怎么用的,它就怎么用(初始化除外)

下一個(gè)專欄正式結(jié)束類與對(duì)象的初步認(rèn)識(shí),內(nèi)存管理,vector,list,stl的內(nèi)容正在學(xué)習(xí),很快就能和大家見面

C++自制心得——類與對(duì)象中(拷貝構(gòu)造+賦值重載)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
淳安县| 定陶县| 呼伦贝尔市| 乡宁县| 四川省| 肃北| 崇文区| 田林县| 高碑店市| 武陟县| 南江县| 恭城| 敖汉旗| 磴口县| 荔浦县| 托克逊县| 沧源| 桂阳县| 霞浦县| 若尔盖县| 扎赉特旗| 莱阳市| 涿鹿县| 津市市| 云林县| 页游| 泰安市| 筠连县| 宝应县| 宣汉县| 靖江市| 汉沽区| 清水县| 稻城县| 长寿区| 南城县| 岱山县| 阿城市| 九江县| 长子县| 竹北市|