WordPress太占空間了如何優(yōu)化培訓(xùn)體系
前言:
??上一篇小編講了類(lèi)和對(duì)象(1),當(dāng)然,在看這篇文章之前,讀者朋友們一定要掌握好前面的基礎(chǔ)內(nèi)容,因?yàn)檫@篇和前面息息相關(guān),廢話不多說(shuō),下面小編就加快步伐,開(kāi)始今天這篇文章的講解。
目錄
1.類(lèi)的默認(rèn)成員函數(shù)
2.構(gòu)造函數(shù)
?2.1.構(gòu)造函數(shù)的概念
?2.2.構(gòu)造函數(shù)的特點(diǎn)
?2.1.1.前四個(gè)特點(diǎn)
?2.1.2.后三個(gè)特點(diǎn)
3.析構(gòu)函數(shù)
?3.1.析構(gòu)函數(shù)的概念
?3.2.析構(gòu)函數(shù)的特點(diǎn)?
?3.2.1.前四個(gè)特點(diǎn)
3.2.2.后四個(gè)特點(diǎn)
4.拷貝構(gòu)造函數(shù)
4.1.拷貝構(gòu)造函數(shù)的概念
4.2.拷貝構(gòu)造函數(shù)的特點(diǎn)
?4.2.1.前三個(gè)特點(diǎn)
?4.2.2.后三個(gè)特點(diǎn)
5.賦值運(yùn)算符重載
5.1.運(yùn)算符重載
?5.1.1.運(yùn)算符重載前幾個(gè)特點(diǎn)
. 5.1.2.運(yùn)算符重載的后幾個(gè)特點(diǎn)?編輯
5.2.賦值運(yùn)算符重載的書(shū)寫(xiě)
6.取地址運(yùn)算符重載
6.1.const成員函數(shù)
6.2.取地址運(yùn)算符重載
7.總結(jié)
正文:
1.類(lèi)的默認(rèn)成員函數(shù)
? 默認(rèn)成員函數(shù)就是用戶(hù)沒(méi)有顯示實(shí)現(xiàn)(大白話來(lái)講就是沒(méi)有寫(xiě)相關(guān)的函數(shù)),編譯器自動(dòng)生成的成員函數(shù)就被稱(chēng)之為默認(rèn)成員函數(shù)。一個(gè)類(lèi),在我們不寫(xiě)的時(shí)候編譯器會(huì)形成一下六個(gè)默認(rèn)成員函數(shù):
? 不過(guò)值得注意的是,這6個(gè)成員函數(shù)中,前四個(gè)是比較重要的,小編今天首先是要講完這四個(gè)函數(shù),至于后兩個(gè)小編準(zhǔn)備在下一篇在講,不過(guò)最后兩個(gè)理解一下就好,目前我們不需要太多了解,前四個(gè)是我們要知道的,這對(duì)于我們以后的學(xué)習(xí)有很大的意義!C++11以后還會(huì)增加兩個(gè)成員函數(shù),這兩個(gè)成員函數(shù)小編還沒(méi)學(xué)到,所以先放一放。默認(rèn)成員函數(shù)是一個(gè)很重要的概念,但是也是很復(fù)雜的,我們需要從以下兩個(gè)方面去了解:
? 我們已經(jīng)了解了默認(rèn)成員函數(shù)是什么了,下面我們開(kāi)始深層次的進(jìn)入講解,下面登場(chǎng)的是:構(gòu)造函數(shù)!
2.構(gòu)造函數(shù)
?2.1.構(gòu)造函數(shù)的概念
??可能會(huì)多讀者朋友看到這個(gè)函數(shù)的名字,會(huì)自己認(rèn)為這個(gè)函數(shù)就是來(lái)開(kāi)空間創(chuàng)造對(duì)象的,那可就大錯(cuò)特錯(cuò)了,構(gòu)造函數(shù)是對(duì)象進(jìn)行實(shí)例化以后對(duì)對(duì)象進(jìn)行初始化的。小編之前也寫(xiě)過(guò)棧和隊(duì)列這兩種數(shù)據(jù)結(jié)構(gòu),在當(dāng)時(shí)小編就寫(xiě)了初始化函數(shù)Init,而構(gòu)造函數(shù)的本質(zhì)就是用來(lái)替代棧和隊(duì)列的Init函數(shù)的,因?yàn)楫?dāng)我們寫(xiě)完構(gòu)造函數(shù)以后,編譯器是會(huì)自動(dòng)調(diào)用構(gòu)造函數(shù)的,所以構(gòu)造函數(shù)是可以完美替代Init函數(shù)的,這便是構(gòu)造函數(shù)的概念,當(dāng)我們了解完概念以后,下面就要開(kāi)始進(jìn)入構(gòu)造函數(shù)的特點(diǎn)講解了!
?2.2.構(gòu)造函數(shù)的特點(diǎn)
?2.1.1.前四個(gè)特點(diǎn)
? 小編先從這四個(gè)方面進(jìn)行講解,先從第一點(diǎn)進(jìn)行講解:對(duì)于這個(gè)特點(diǎn),就是我們?cè)趯?xiě)構(gòu)造函數(shù)的時(shí)候的函數(shù)名是和類(lèi)的名字是一樣的,對(duì)于它的返回點(diǎn),第二個(gè)特點(diǎn)已經(jīng)告訴我們了,它是不需要有返回值的,下面小編就就簡(jiǎn)單的寫(xiě)一個(gè)日期類(lèi)的構(gòu)造函數(shù)來(lái)幫助各位讀者朋友進(jìn)行了解:
using namespace std;class date
{
public:date() //構(gòu)造函數(shù)是可以重載的,參數(shù)可以帶也可以不帶,后面會(huì)說(shuō){_year = 2024;_month = 8;_day = 13;}
private:int _year;int _month;int _day;
};
? 通過(guò)上面的代碼可以幫組各位讀者朋友了解構(gòu)造函數(shù)的寫(xiě)法,這只是構(gòu)造函數(shù)的一種,小編在代碼里也說(shuō)過(guò),構(gòu)造函數(shù)的形參可以有,也可以沒(méi)有,因?yàn)榈谒膫€(gè)特點(diǎn)就說(shuō)明了:構(gòu)造函數(shù)是可以重載的,所以構(gòu)造函數(shù)我們?cè)跁?shū)寫(xiě)的時(shí)候有時(shí)候帶參,有時(shí)候不帶參數(shù),但是小編推薦各位讀者朋友可以寫(xiě)一個(gè)全缺省的構(gòu)造函數(shù),因?yàn)檫@樣比較方便。我們已經(jīng)講述了構(gòu)造函數(shù)的三個(gè)特點(diǎn),接下來(lái)就是第三個(gè)特點(diǎn)還沒(méi)有說(shuō),其實(shí)小編在之前也提過(guò)一嘴,對(duì)于構(gòu)造函數(shù),我們?cè)趯?shí)例化對(duì)象以后編譯器是會(huì)自動(dòng)調(diào)用的,下面小編展示一下如何使用構(gòu)造函數(shù):
using namespace std;class date
{
public:date(int year = 2024,int month = 8,int day = 13) //構(gòu)造函數(shù)是可以重載的,參數(shù)可以帶也可以不帶,后面會(huì)說(shuō){_year = 2024;_month = 8;_day = 13;}
private:int _year;int _month;int _day;
};
int main()
{date s1(2024,8,14); //對(duì)于全缺省的構(gòu)造函數(shù)的調(diào)用,我們僅需在對(duì)象后直接用括號(hào)然后放入我們想要的實(shí)參就好了,或者我們不需要這么寫(xiě)。date s2; //對(duì)于全缺省的或者不帶參的也可以這么寫(xiě)return 0;
}
? 對(duì)于構(gòu)造函數(shù)的使用,正如小編上面的代碼圖一樣,此時(shí)我們可以分為兩種情況,一種是必須要寫(xiě)實(shí)參的,那個(gè)時(shí)候就是我們把上面代碼的缺省值給全去掉,此時(shí)我們就必須要寫(xiě)實(shí)參了,還有一種就是不帶參數(shù)或者全缺省的,此時(shí)不帶參的我們不寫(xiě)實(shí)參,而全缺省的我們可以不用寫(xiě)實(shí)參,當(dāng)然也可以寫(xiě),但一般我們都會(huì)寫(xiě)的,小編在之后講完整時(shí)間類(lèi)的時(shí)候就推薦各位去寫(xiě)。此時(shí)就是構(gòu)造函數(shù)的前四個(gè)特點(diǎn),前四個(gè)特點(diǎn)還是比較容易理解的,各位一定要好好的知道并且理解這些特點(diǎn),下面我們開(kāi)始講述后三個(gè)特點(diǎn)。
?2.1.2.后三個(gè)特點(diǎn)
? 先看第五個(gè)特點(diǎn),它告訴了我們?nèi)绻覀儾粚?xiě)構(gòu)造函數(shù)的話,系統(tǒng)是會(huì)幫助我們生成一個(gè)默認(rèn)構(gòu)造函數(shù),這個(gè)特點(diǎn)應(yīng)該搭配著第七個(gè)特點(diǎn)進(jìn)行查看,對(duì)于我們不寫(xiě),系統(tǒng)默認(rèn)生成的構(gòu)造,對(duì)于內(nèi)置類(lèi)型的構(gòu)造是不確定的,可能很多讀者朋友不知道內(nèi)置類(lèi)型是什么意思,小編在這里簡(jiǎn)單的說(shuō)一下,內(nèi)置類(lèi)型是編譯器默認(rèn)安置一些簡(jiǎn)單的類(lèi)型,就比如整型,浮點(diǎn)型等等,這些都是內(nèi)置類(lèi)型,而內(nèi)置類(lèi)型如果不寫(xiě)構(gòu)造函數(shù)的話,對(duì)于它是否可以進(jìn)行初始化,這個(gè)是要看編譯器的,下面小編用VS2022的編譯器來(lái)帶著大家去看一看如果我們對(duì)于內(nèi)置類(lèi)型的類(lèi)不寫(xiě)構(gòu)造會(huì)怎么樣:
? 如上圖所示,此時(shí)編譯器實(shí)際上并沒(méi)有給我們進(jìn)行初始化,所以上面說(shuō)過(guò),內(nèi)置類(lèi)型系統(tǒng)給我們的構(gòu)造函數(shù)是要看編譯器的,如果不給我們初始化那也是很正常的,所以我們要有自己寫(xiě)初始化奇函數(shù)的習(xí)慣!這個(gè)在之后的學(xué)習(xí)生活都是很重要的,我們繼續(xù)接著第七點(diǎn)進(jìn)行看,對(duì)于自定義類(lèi)型的成員,編譯器會(huì)默認(rèn)去調(diào)用它自己的構(gòu)造函數(shù),如果沒(méi)有的話是會(huì)報(bào)錯(cuò)的,可能很多讀者朋友不知道自定義類(lèi)型有什么,小編也說(shuō)說(shuō),自定義類(lèi)型就是一些復(fù)雜的類(lèi)型,比如結(jié)構(gòu)體,類(lèi),這些都是我們?nèi)プ约憾x的類(lèi)型,所以是自定義類(lèi)型,對(duì)于自定義類(lèi)型的成員的書(shū)寫(xiě),小編在之前寫(xiě)過(guò)隊(duì)列的習(xí)題中,我們用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的時(shí)候MyQueue,成員函數(shù)就是兩個(gè)自定義類(lèi)型,這時(shí)候我們是不需要寫(xiě)構(gòu)造函數(shù)的,此時(shí)這倆自定義是會(huì)自己調(diào)用自己的構(gòu)造函數(shù)的,只不過(guò)我們需要去寫(xiě)它們各自的構(gòu)造函數(shù)的罷了,下面小編來(lái)講一下我沒(méi)講的最后一個(gè)特點(diǎn),也就是第六個(gè)特點(diǎn)!
? 第六個(gè)特點(diǎn)告訴我們默認(rèn)構(gòu)造函數(shù)的相關(guān)概念,很多讀者朋友看到這個(gè)名字,可能就是覺(jué)得系統(tǒng)默認(rèn)給我們的構(gòu)造函數(shù)就是默認(rèn)構(gòu)造函數(shù),其實(shí)這是默認(rèn)構(gòu)造函數(shù)的一種,默認(rèn)構(gòu)造函數(shù)還有無(wú)參的構(gòu)造,全缺省的構(gòu)造,這三個(gè)類(lèi)型的默認(rèn)構(gòu)造函數(shù)我們?cè)趯?xiě)的時(shí)候只能出現(xiàn)一次,不能同時(shí)存在,如果我們不寫(xiě)構(gòu)造函數(shù),那就代表第一種(編譯器默認(rèn)給的構(gòu)造函數(shù))存在,如果我們寫(xiě)了無(wú)參的默認(rèn)構(gòu)造,那么全缺省我們不能在寫(xiě),雖然在語(yǔ)法上這樣是可以的,但是會(huì)產(chǎn)生歧義,因?yàn)槿绻覀儾粚?xiě)實(shí)參編譯器不知道會(huì)調(diào)用哪一個(gè)函數(shù),所以說(shuō)這三種類(lèi)型只能出現(xiàn)其中一個(gè),我們?cè)趯?xiě)構(gòu)造函數(shù)的時(shí)候一般也就寫(xiě)默認(rèn)構(gòu)造函數(shù),小編還是推薦各位讀者朋友用全缺省的默認(rèn)構(gòu)造函數(shù),這樣比較省心點(diǎn)。
? 此時(shí)小編已經(jīng)講述了構(gòu)造函數(shù)的全部特點(diǎn)了,那么現(xiàn)在我們加快腳步,開(kāi)始進(jìn)入下一個(gè)函數(shù):析構(gòu)函數(shù)的講解!
3.析構(gòu)函數(shù)
?3.1.析構(gòu)函數(shù)的概念
??析構(gòu)函數(shù)這個(gè)名字,相信很多讀者朋友看到這個(gè)名字的第一印象就是把對(duì)象給銷(xiāo)毀的函數(shù),小編當(dāng)時(shí)也是這么想的,但其實(shí)它的作用是和構(gòu)造函數(shù)相反的,析構(gòu)函數(shù)是用來(lái)對(duì)對(duì)象中的資源進(jìn)行釋放的,這些資源就比如我們?cè)趯?xiě)棧的時(shí)候我們動(dòng)態(tài)內(nèi)存開(kāi)辟的空間,文件操作時(shí)產(chǎn)生的資源等等,這便是析構(gòu)函數(shù)的作用,可以把它看作是它是來(lái)替代我們以前寫(xiě)過(guò)的銷(xiāo)毀函數(shù)的,另外小編在說(shuō)一下對(duì)于對(duì)象的銷(xiāo)毀,我們?cè)谠O(shè)置對(duì)象的時(shí)候把對(duì)象放在了函數(shù)這個(gè)棧幀中,當(dāng)我們出去函數(shù)棧幀的時(shí)候,編譯器就會(huì)幫助我們把對(duì)象給銷(xiāo)毀了,所以我們無(wú)須在自己銷(xiāo)毀對(duì)象了,這是編譯器給予我們的便利性,以上就是析構(gòu)函數(shù)的概念,下面小編來(lái)講述一下析構(gòu)函數(shù)的特點(diǎn)。
?3.2.析構(gòu)函數(shù)的特點(diǎn)?
?3.2.1.前四個(gè)特點(diǎn)
? 先從第一點(diǎn),第二點(diǎn)來(lái)看,析構(gòu)函數(shù)的命名特點(diǎn)和前面的構(gòu)造函數(shù)是有一點(diǎn)類(lèi)似的, 它們都是不需要返回值的,只不過(guò)對(duì)于函數(shù)的命名,析構(gòu)函數(shù)比構(gòu)造函數(shù)多了個(gè)~,這個(gè)符號(hào)在C語(yǔ)言中有按位取反的意思,我們記析構(gòu)函數(shù)的時(shí)候也可以這么記,因?yàn)檎梦鰳?gòu)函數(shù)和構(gòu)造函數(shù)兩個(gè)函數(shù)的功能是相反的,所以我們用~也是正常的,我們繼續(xù)看第二個(gè)特點(diǎn),析構(gòu)函數(shù)是沒(méi)有參數(shù)的,自然不會(huì)在有函數(shù)重載,從而可以比較好理解第三個(gè)特點(diǎn):一個(gè)類(lèi)只允許有一個(gè)析構(gòu)函數(shù),因?yàn)槲鰳?gòu)函數(shù)無(wú)參,不可以函數(shù)重載,下面小編先寫(xiě)個(gè)析構(gòu)函數(shù)來(lái)幫助讀者朋友知道我們?nèi)绾问褂梦鰳?gòu)函數(shù):
//一般來(lái)說(shuō)內(nèi)置類(lèi)型我們不需要析構(gòu)函數(shù)的,因?yàn)閮?nèi)置類(lèi)型沒(méi)有用到資源,所以小編就拿之前講過(guò)的棧舉例子,因?yàn)闂?dòng)態(tài)開(kāi)辟了空間
class Strack
{
public:Strack(int n = 4){arr = (int*)malloc(sizeof(int) * n);capciaty = n;top = 0;cout << "Strack()" << endl;}~Strack(){free(arr);arr = NULL;capciaty = top = 0;cout << "~Strack()" <<endl; //這里使用打印是為了后續(xù)自定義類(lèi)型的成員默認(rèn)去調(diào)用自己的析構(gòu)函數(shù),幫助各位讀者朋友去理解的}
private:int top; //棧頂元素int capciaty; //總空間大小int* arr;
};
? 上面就是構(gòu)造函數(shù)和析構(gòu)函數(shù)的書(shū)寫(xiě),小編在概念的時(shí)候也說(shuō)過(guò),析構(gòu)函數(shù)就是來(lái)完美替代銷(xiāo)毀函數(shù)的,它的書(shū)寫(xiě)和銷(xiāo)毀函數(shù)是類(lèi)似的,不過(guò)我們?cè)趯?xiě)銷(xiāo)毀函數(shù)的時(shí)候,我們還需要去調(diào)用函數(shù),但是析構(gòu)函數(shù)是不需要我們手動(dòng)調(diào)用的,第四個(gè)特點(diǎn)說(shuō)了,在我們寫(xiě)的主函數(shù)生命周期結(jié)束以后,析構(gòu)函數(shù)是會(huì)去自動(dòng)調(diào)用的,所以說(shuō)我們只要寫(xiě)完了析構(gòu)函數(shù)以后,我們就無(wú)需在主函數(shù)中去使用它,編譯器會(huì)幫助我們?nèi)プ詣?dòng)調(diào)用這個(gè)函數(shù)的,所以這么做可以幫助那些常忘記寫(xiě)銷(xiāo)毀函數(shù)的讀者朋友,這也是C++對(duì)于C的增強(qiáng),以上就是前四個(gè)特點(diǎn),下面小編來(lái)講述剩下的幾個(gè)特點(diǎn)!
3.2.2.后四個(gè)特點(diǎn)
? ?先從頭開(kāi)始看起,析構(gòu)函數(shù)和構(gòu)造函數(shù)的相似之處是有很多的,我們不寫(xiě)析構(gòu)函數(shù)的時(shí)候,對(duì)于內(nèi)置類(lèi)型的成員不用處理,對(duì)于自定義類(lèi)型的成員就需要去調(diào)用它自己的析構(gòu)函數(shù),對(duì)于自定義類(lèi)型的成員,小編這里就寫(xiě)個(gè)雙棧實(shí)現(xiàn)隊(duì)列的數(shù)據(jù)結(jié)構(gòu)來(lái)幫助讀者朋友去理解它們的析構(gòu)函數(shù)是會(huì)自己調(diào)用的。
class MyQueue
{
private:Strack s1;Strack s2;
};int main()
{MyQueue a1;return 0;
}
? 通過(guò)打印結(jié)果我們可以清晰的看出此時(shí)編譯器自動(dòng)幫我們?nèi)フ{(diào)用了自定義類(lèi)型的析構(gòu)函數(shù)和構(gòu)造函數(shù),所以對(duì)于自定義類(lèi)型的成員我們無(wú)須去自己寫(xiě)構(gòu)造函數(shù),當(dāng)然我們也可以寫(xiě),但是寫(xiě)的話會(huì)顯的代碼很贅余,我們寫(xiě)代碼自然是越簡(jiǎn)潔越好,太長(zhǎng)了的話后續(xù)我們找錯(cuò)誤的代碼的時(shí)候會(huì)很累的,此時(shí)印證了第六個(gè)特點(diǎn),自定義類(lèi)型是會(huì)自己去調(diào)用自己的析構(gòu)函數(shù)的,我們?cè)倏吹谄邆€(gè)特點(diǎn),對(duì)于一些不需要去申請(qǐng)資源的類(lèi),我們就不需要寫(xiě)析構(gòu)函數(shù),就比如小編之前寫(xiě)過(guò)的簡(jiǎn)易時(shí)間類(lèi),這個(gè)類(lèi)就不需要去寫(xiě)析構(gòu)函數(shù),因?yàn)樗某蓡T變量都沒(méi)涉及到一些資源;當(dāng)然,小編上面寫(xiě)的代碼,對(duì)于只有自定義類(lèi)型成員的類(lèi),我們也不需要寫(xiě)析構(gòu)函數(shù),因?yàn)樗鼤?huì)去自動(dòng)調(diào)用各自的析構(gòu)函數(shù);對(duì)于小編寫(xiě)過(guò)的Strack類(lèi),這個(gè)棧因?yàn)樯婕暗搅藙?dòng)態(tài)內(nèi)存的使用,也就是資源的使用,所以我們就必須要寫(xiě)析構(gòu)函數(shù),編譯器是不會(huì)對(duì)這些動(dòng)態(tài)開(kāi)辟的空間進(jìn)行自主釋放的。接下來(lái)就是最后一個(gè)特點(diǎn),這個(gè)特點(diǎn)也說(shuō)的很清晰明了,對(duì)于類(lèi)里面涉及到的多個(gè)對(duì)象,最后定義的成員是會(huì)先析構(gòu)的,這個(gè)特點(diǎn)搭配著調(diào)試功能會(huì)更好看出來(lái),各位讀者朋友記住這個(gè)功能就好,之后小編在講解一些題目的時(shí)候可能會(huì)涉及到,下面我們進(jìn)入第三個(gè)默認(rèn)成員函數(shù)——拷貝構(gòu)造函數(shù)。
4.拷貝構(gòu)造函數(shù)
4.1.拷貝構(gòu)造函數(shù)的概念
? 如果一個(gè)函數(shù)的第一個(gè)參數(shù)是自身類(lèi)類(lèi)型的引用,且任何額外的參數(shù)都有默認(rèn)值,則此構(gòu)造函數(shù)也叫做拷貝構(gòu)造函數(shù),也就是說(shuō)拷貝構(gòu)造函數(shù)是一個(gè)比較特殊的構(gòu)造函數(shù)。簡(jiǎn)單來(lái)說(shuō),拷貝構(gòu)造函數(shù)就是把一個(gè)類(lèi)類(lèi)型的對(duì)象賦值給一個(gè)剛創(chuàng)建的對(duì)象,類(lèi)似下面這樣:
A a; //此時(shí)就默認(rèn)已經(jīng)調(diào)用構(gòu)造函數(shù)了
A d = a;
4.2.拷貝構(gòu)造函數(shù)的特點(diǎn)
?4.2.1.前三個(gè)特點(diǎn)
? 1.拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的重載。對(duì)于這句話,可能一些讀者朋友看著會(huì)懵,因?yàn)楦魑贿€不知道拷貝構(gòu)造函數(shù)如何去寫(xiě),等會(huì)小編會(huì)結(jié)合第二個(gè)特點(diǎn)來(lái)說(shuō)寫(xiě)法的,各位可以先知道拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的重載就行~
?2.拷貝構(gòu)造函數(shù)第一個(gè)參數(shù)必須是類(lèi)類(lèi)型對(duì)象的引用,使用傳值的方式編譯器會(huì)直接進(jìn)行報(bào)錯(cuò)的,因?yàn)檎Z(yǔ)法邏輯上會(huì)造成無(wú)線遞歸(這個(gè)特點(diǎn)小編等會(huì)會(huì)告訴各位這是為何的),拷貝構(gòu)造函數(shù)也可以有多個(gè)參數(shù),但是第一個(gè)參數(shù)一定是類(lèi)類(lèi)型對(duì)象的引用,后面的參數(shù)必須有缺省值。對(duì)于這個(gè)特點(diǎn),小編有話說(shuō),首先我們從開(kāi)頭開(kāi)始看,此時(shí)這個(gè)特點(diǎn)告訴我們拷貝構(gòu)造函數(shù)第一個(gè)參數(shù)是類(lèi)類(lèi)型對(duì)象的引用,結(jié)合第一個(gè)特點(diǎn),拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的重載,這里我們就可以大致推斷出拷貝構(gòu)造函數(shù)是如何去寫(xiě)的,此時(shí)我們還是不用去寫(xiě)返回類(lèi)型(這個(gè)重點(diǎn),這篇文章小編隔了半個(gè)月重新去寫(xiě),我重新練習(xí)這部分內(nèi)容的時(shí)候,我就忘記了拷貝構(gòu)造函數(shù)是沒(méi)有返回值的,直到我寫(xiě)了這篇文章才反應(yīng)過(guò)來(lái)),函數(shù)名就是類(lèi)的名字,括號(hào)里面是一個(gè)類(lèi)類(lèi)型對(duì)象的引用,下面小編就書(shū)寫(xiě)拷貝構(gòu)造函數(shù):
using namespace std;class A
{
public:A(int time = 2024){_time = time;}A(const A& x) //加const是為了防止權(quán)限放大,權(quán)限可以平等也可以去放大{_time = x._time; //把x的內(nèi)容復(fù)制給*this就好}
private:int _time;
};
? 上面就是我們?nèi)粘?shū)寫(xiě)的拷貝構(gòu)造函數(shù),各位讀者朋友要培養(yǎng)這么寫(xiě)拷貝構(gòu)造函數(shù),以后我們有很多地方需要用到拷貝構(gòu)造函數(shù),之后我們?cè)偻罂?#xff0c;后面這句話告訴我們我們?cè)跁?shū)寫(xiě)拷貝構(gòu)造函數(shù)的時(shí)候一定要傳引用,而不是去直接傳類(lèi)類(lèi)型的對(duì)象,對(duì)于這個(gè)原因,小編就從這里開(kāi)始進(jìn)行解釋,這里就牽扯到了下一個(gè)特點(diǎn):當(dāng)我們?cè)谡{(diào)用類(lèi)類(lèi)型對(duì)象的時(shí)候,會(huì)先進(jìn)行一次拷貝構(gòu)造以后在傳過(guò)去,這個(gè)點(diǎn)各位讀者朋友一定要記住,對(duì)于為什么這樣做,小編也不是很清楚(理直氣壯),這涉及到了深拷貝和淺拷貝,以后小編了解多了以后會(huì)在進(jìn)行補(bǔ)充,所以這個(gè)點(diǎn)就說(shuō)明了為什么我們要傳引用,如果直接傳類(lèi)類(lèi)型的時(shí)候,會(huì)先去進(jìn)行一次拷貝構(gòu)造,如果我們不寫(xiě)出這個(gè)拷貝構(gòu)造的話,那么會(huì)一直循環(huán)去找拷貝構(gòu)造,從而造成死循環(huán),這就是為什么會(huì)在語(yǔ)法邏輯上無(wú)限遞歸。繼續(xù)往后面的特點(diǎn)看,他告訴我們?cè)诶ㄌ?hào)里面還可以寫(xiě)除了類(lèi)類(lèi)型引用外其他的東西,這個(gè)知道就好,一般我們寫(xiě)拷貝構(gòu)造函數(shù)的時(shí)候,我們僅僅寫(xiě)類(lèi)類(lèi)型引用即可,這便是拷貝構(gòu)造函數(shù)第二個(gè)特點(diǎn),下面我們繼續(xù)看第三個(gè)特點(diǎn):
? 3.C++規(guī)定自定義類(lèi)型對(duì)象進(jìn)行拷貝行為必須調(diào)用拷貝構(gòu)造,所以這里自定義類(lèi)型傳值傳參和傳值返回都會(huì)去調(diào)用拷貝構(gòu)造。這個(gè)特點(diǎn)小編在上面就已經(jīng)說(shuō)了,所以就不多贅述了,這是拷貝構(gòu)造函數(shù)的前三個(gè)特點(diǎn),下面我們進(jìn)行后三個(gè)特點(diǎn)的講述。
?4.2.2.后三個(gè)特點(diǎn)
? 1.若未顯示定義拷貝構(gòu)造,編譯器會(huì)自動(dòng)生成拷貝構(gòu)造函數(shù)。自動(dòng)生成的拷貝構(gòu)造對(duì)內(nèi)置類(lèi)型成員變量會(huì)完成淺拷貝(一個(gè)字節(jié)一個(gè)字節(jié)的進(jìn)行拷貝),對(duì)自定義類(lèi)型的成員變量會(huì)調(diào)用它的拷貝構(gòu)造函數(shù)。和前面兩個(gè)默認(rèn)成員函數(shù)一樣,拷貝構(gòu)造我們不寫(xiě)編譯器也會(huì)去自己生成一個(gè)拷貝構(gòu)造函數(shù),這時(shí)候可能有很多讀者朋友會(huì)說(shuō)了,這不是一件好事嗎?如果這么想那就是大錯(cuò)特錯(cuò)了,因?yàn)榇藭r(shí)系統(tǒng)給我們生成的拷貝構(gòu)造函數(shù)是進(jìn)行淺拷貝,可能很多讀者朋友不知道什么叫做淺拷貝,這里小編給出解釋,此時(shí)如果我們?cè)O(shè)置了一個(gè)成員變量_a,實(shí)例化一個(gè)對(duì)象a,我們把a(bǔ)的_a淺拷貝給實(shí)例化后的b的_a,此時(shí)我們需要把a(bǔ)的地址一個(gè)字節(jié)一個(gè)字節(jié)的拷貝給b,類(lèi)似于下圖這樣:
? 上圖就展示了如果我們不寫(xiě)拷貝構(gòu)造函數(shù)的話,僅僅使用淺拷貝會(huì)發(fā)生的事情,如果我們動(dòng)態(tài)開(kāi)辟一塊空間,實(shí)例化多個(gè)對(duì)象,如果一個(gè)對(duì)象進(jìn)行了釋放操作,那么經(jīng)過(guò)它拷貝構(gòu)造出來(lái)的所有對(duì)象就會(huì)全部釋放,這樣的話我們這個(gè)類(lèi)就沒(méi)有什么意義了,所以此時(shí)我們就要通過(guò)寫(xiě)拷貝構(gòu)造函數(shù)經(jīng)過(guò)深拷貝,深拷貝不再是一個(gè)字節(jié)一個(gè)字節(jié)的進(jìn)行拷貝,而是會(huì)先開(kāi)辟出一塊空間,然后把a(bǔ)這個(gè)對(duì)象的值復(fù)制到新建立的空間中,就如下圖所示:
? 這樣我們就可以很好的去實(shí)現(xiàn)了真正意義上的拷貝,之后我們往后看,可以知道拷貝構(gòu)造函數(shù)對(duì)待類(lèi)類(lèi)型的成員變量的時(shí)候,也還是會(huì)進(jìn)行調(diào)用它們各自的拷貝構(gòu)造函數(shù),這就是第四個(gè)特點(diǎn),接下來(lái)我們繼續(xù)往后走:
? 5.由于第五個(gè)特點(diǎn)篇幅很長(zhǎng),所以我索性就給一個(gè)圖片了:
? 這個(gè)特點(diǎn)是想告訴我們什么時(shí)候再去寫(xiě)拷貝構(gòu)造函數(shù),拷貝構(gòu)造函數(shù)并非是一定要寫(xiě)的,如我們之前寫(xiě)的時(shí)間類(lèi),這個(gè)類(lèi)的成員就沒(méi)有涉及到動(dòng)態(tài)內(nèi)存開(kāi)辟等等利用資源的方式,所以我們就無(wú)須在寫(xiě)拷貝構(gòu)造函數(shù),我們通過(guò)簡(jiǎn)單的淺拷貝便可以達(dá)到我們的目的,深拷貝是對(duì)那些申請(qǐng)資源的類(lèi)有要求,一般申請(qǐng)資源的話就必須去寫(xiě)拷貝構(gòu)造函數(shù),當(dāng)然這個(gè)特點(diǎn)也告訴我們?nèi)绾稳ヅ袛嗍欠駥?xiě)拷貝構(gòu)造函數(shù),當(dāng)這個(gè)類(lèi)必須寫(xiě)析構(gòu)函數(shù)的時(shí)候并且涉及到了釋放資源的過(guò)程,那么拷貝構(gòu)造函數(shù)是我們一定要去寫(xiě)的,這就是第五個(gè)特點(diǎn),雖然很長(zhǎng),但理解起來(lái)還是比較簡(jiǎn)單的~?
?6.特單比較長(zhǎng),我就直接圖片代文字餓了
? 這個(gè)特點(diǎn)各位讀者朋友記住就好,小編感覺(jué)這個(gè)解釋就已經(jīng)很詳細(xì)了,并且如果我沒(méi)有記錯(cuò)的話,我在上一篇文章或者上上篇文章就說(shuō)明了野引用問(wèn)題,各位讀者朋友應(yīng)該盡量避免野引用的出現(xiàn),以上便就是拷貝構(gòu)造函數(shù)的特點(diǎn),下面我們進(jìn)入下一個(gè)默認(rèn)成員函數(shù)——賦值運(yùn)算符的重載。
5.賦值運(yùn)算符重載
5.1.運(yùn)算符重載
? 再講解賦值運(yùn)算符之前,小編先講述一下什么叫做運(yùn)算符重載,簡(jiǎn)單來(lái)說(shuō),運(yùn)算符重載就是讓我們可以用類(lèi)做加減乘除,比大小等等一系列功能, 等會(huì)我們講述的賦值運(yùn)算符就是其中的一種,下面小編先給各位展示運(yùn)算符重載的幾個(gè)特點(diǎn):
?5.1.1.運(yùn)算符重載前幾個(gè)特點(diǎn)
? 從頭開(kāi)始看,開(kāi)頭就告訴我們想要將運(yùn)算符用于類(lèi)類(lèi)型對(duì)象的時(shí)候,就必須去通過(guò)運(yùn)算符重載的形式去進(jìn)行定義,我們?cè)谶M(jìn)行類(lèi)類(lèi)型對(duì)象的加減的時(shí)候,此時(shí)我們就默認(rèn)的去調(diào)用了相應(yīng)的運(yùn)算符重載,不然是會(huì)報(bào)錯(cuò)的,我們?cè)倏吹诙€(gè)點(diǎn),第二個(gè)點(diǎn)告訴了我們?nèi)绾螘?shū)寫(xiě)一個(gè)運(yùn)算符重載,特點(diǎn)已經(jīng)講述的比較詳細(xì)了,小編等會(huì)寫(xiě)一個(gè)代碼來(lái)幫助各位讀者朋友去了解,我們繼續(xù)往后看,第三個(gè)特點(diǎn)告訴我們?nèi)绾稳?xiě)一個(gè)運(yùn)算符重載,這是由運(yùn)算符作用的對(duì)象來(lái)決定的,就比如我們想寫(xiě)大于等于等等比較類(lèi)型的運(yùn)算符,那么我們就需要有兩個(gè)參數(shù),如果我們想去寫(xiě)三目運(yùn)算符,那我們就要有三個(gè)參數(shù)(但是三目操作符是不可以重載的,后面特點(diǎn)會(huì)說(shuō))等等,這就是這個(gè)特點(diǎn)要講的;下面我們繼續(xù)往后看,它說(shuō)明了如果我們把操作符重載作為類(lèi)成員函數(shù),此時(shí)我們參數(shù)就可以少寫(xiě)一個(gè),因?yàn)槲覀兌贾李?lèi)里面的成員函數(shù)都有一個(gè)隱藏的this指針,所以參數(shù)可以少寫(xiě)一個(gè),并且我們?nèi)绻麜?shū)寫(xiě)了很多的運(yùn)算符重載,應(yīng)該大多數(shù)都是類(lèi)的成員函數(shù),不然我們是用不了類(lèi)的成員變量的(一般成員變量都是私有的),當(dāng)然可以有很多辦法可以解決這個(gè)問(wèn)題,這都是后話了,但小編認(rèn)為還是自己的成員函數(shù)放心,最后一個(gè)特點(diǎn)各位讀者朋友記住就好,下面我們繼續(xù)后幾個(gè)特點(diǎn)的講述,在講述之前小編先給各位讀者朋友展示一個(gè)大于操作符的重載:
class Time
{
public:Time(int time = 122){_time = time;}bool operator>(Time& x){return _time > x._time;}
private:int _time;
};
. 5.1.2.運(yùn)算符重載的后幾個(gè)特點(diǎn)
? 先看第一個(gè),這個(gè)特點(diǎn)是很通俗易懂的,我們運(yùn)算符重載,肯定是重載有意義的運(yùn)算符,而不是自己造個(gè)新運(yùn)算符,不然不如叫運(yùn)算符構(gòu)造得了~各位讀者朋友記住這個(gè)特點(diǎn)就好,下面一個(gè)特點(diǎn)就解釋了小編講述運(yùn)算符重載函數(shù)參數(shù)的時(shí)候,為什么說(shuō)我們不可以重載三目操作符,因?yàn)镃++規(guī)定了我們不可以去重載,至于原因大家不必深究,直到不能用就好,在以后我們不斷的學(xué)習(xí)中可能就知道祖師爺為什么不讓我們?nèi)ブ剌d這個(gè)了,之后的幾個(gè)特點(diǎn)讀者朋友看著就能理解,小編就不在多敘述了(等小編講述時(shí)間類(lèi)的時(shí)候就會(huì)對(duì)其中幾個(gè)多做說(shuō)明),下面我們就先重載一個(gè)運(yùn)算符:賦值運(yùn)算符~
5.2.賦值運(yùn)算符重載的書(shū)寫(xiě)
? 首先我們?cè)趯?xiě)運(yùn)算符重載的時(shí)候我們需要注意返回類(lèi)型,由于此時(shí)我們是賦值運(yùn)算符重載,所以返回的類(lèi)型肯定就是類(lèi)類(lèi)型,此時(shí)我們?cè)诜祷氐臅r(shí)候可以傳引用返回,減少臨時(shí)空間的產(chǎn)生,增加代碼的效率,此時(shí)我們是需要把賦值運(yùn)算符重載作為類(lèi)成員函數(shù)的,所以此時(shí)我們僅需寫(xiě)一個(gè)形參即可,賦值操作涉及到了兩個(gè)類(lèi)的操作,所以我們直接傳一個(gè)類(lèi)類(lèi)型對(duì)象的引用即可,這樣可以減少拷貝構(gòu)造函數(shù)的生成,之后的操作其實(shí)就和我們之前寫(xiě)的拷貝構(gòu)造函數(shù)一樣了,有些讀者朋友可能會(huì)分不清拷貝構(gòu)造函數(shù)和賦值運(yùn)算符兩個(gè)的區(qū)別,他倆的區(qū)別是很容易判別出來(lái)的,拷貝構(gòu)造函數(shù)是把一個(gè)存在的類(lèi)對(duì)象的內(nèi)容深拷貝給一個(gè)剛剛建立的對(duì)象,而賦值運(yùn)算符重載則是針對(duì)于兩個(gè)已經(jīng)存在于類(lèi)對(duì)象,這兩個(gè)函數(shù)針對(duì)的兩個(gè)作用對(duì)象是不同的,所以這就是他們的區(qū)別,下面小編就給各位展示一下賦值運(yùn)算符重載函數(shù)的寫(xiě)法:
class Date
{Date(int year = 2024, int month = 9, int day = 17){_year = year;_month = month;_day = day;}Date(Date& x){_year = x._day;_month = x._month;_day = x._day;}Date& operator>(Date& x){_year = x._year;_month = x._month;_day = x._day;}
private:int _year;int _month;int _day;
};
? 下面我們進(jìn)入下一個(gè)函數(shù)的講解~
6.取地址運(yùn)算符重載
6.1.const成員函數(shù)
? const成員函數(shù)是我們學(xué)習(xí)的第五個(gè)成員函數(shù),這個(gè)成員函數(shù)重要程度和前幾個(gè)相比就很小了,但我們還是要去了解的,此時(shí)const引用其實(shí)就是去限制我們的this指針的,可能很多讀者朋友很好奇它的作用是什么,看看小編下面的代碼就知道是什么意思了:
class wang
{
public:wang(int time = 102){_time = time;}wang(wang& s1){_time = s1._time;}void Print(){cout << _time << endl;}
private:int _time;
};int main()
{const wang s1;s1.Print();return 0;
}
? 猜一猜上面的代碼是否可以運(yùn)行,很顯然,這個(gè)代碼是不可以去運(yùn)行的,報(bào)錯(cuò)原因如下圖所示:
? 此時(shí)我們?cè)O(shè)置的類(lèi)類(lèi)型對(duì)象s1是const類(lèi)型,所以我們?cè)谑褂煤瘮?shù)的時(shí)候,如果我們不傳const類(lèi)型的引用,那么會(huì)出現(xiàn)一種情況:變量自身是無(wú)法被改變的,但是變量的小名卻是可以被改變的,這樣是不符合常理的,所以再給函數(shù)傳變量的時(shí)候,我們需要去傳const類(lèi)型的引用,從而避免權(quán)利放大的問(wèn)題,關(guān)于權(quán)利放大的問(wèn)題小編在之前文章也說(shuō)過(guò),權(quán)利是可以平等或者縮小的,但是不可以出現(xiàn)權(quán)利放大的問(wèn)題,所以如果我們想要讓this指針收到const限制,我們僅需在函數(shù)后面加上const即可,如下面代碼所示:
using namespace std;class wang
{
public:wang(int time = 12){_time = time;}void Print()const{cout << _time << endl;}
private:int _time;
};int main()
{const wang a; //consta.Print();return 0;
}
? 上面小編就展示了const是如何在成員函數(shù)中使用的,我們僅需在括號(hào)后面加上const即可,這便是const成員函數(shù)的用法,這個(gè)是比較容易理解的,并且重要程度比較低的,各位讀者朋友知道它的概念和怎么用即可,下面我們進(jìn)入最后一個(gè)默認(rèn)成員函數(shù)的講解——取地址運(yùn)算符重載。
6.2.取地址運(yùn)算符重載
? 取地址運(yùn)算符重載分為普通取地址運(yùn)算符重載以及const取地址運(yùn)算符重載,一般這兩個(gè)運(yùn)算符編譯器是會(huì)幫助我們自主去生成的,我們直接使用編譯器給我們的即可,不需要自己去實(shí)現(xiàn),除非一種特殊情況的發(fā)生:就比如你和小王兩個(gè)人共同去完成一個(gè)項(xiàng)目,有一天你兩個(gè)突然吵架了,此時(shí)你很像搞小王一下,于是自己寫(xiě)了取地址運(yùn)算符重載,讓小王在使用取地址操作符的時(shí)候取不到類(lèi)的地址,從而做到了惡搞的目的(當(dāng)然這是小編不提倡的,這樣可能會(huì)讓這個(gè)項(xiàng)目直接黃了),所以我們一般在這種情境下去進(jìn)行取地址運(yùn)算符的重載,下面小編就給出取地址運(yùn)算符重載的書(shū)寫(xiě)方式,其實(shí)就是套用了運(yùn)算符重載的知識(shí):
class wang
{
public:wang(int time = 12){_time = time;}void Print()const{cout << _time << endl;}const wang* operator&(){return (wang*)0x11222131;//這是惡搞別人的版本return this; //正經(jīng)版本}
private:int _time;
};
7.總結(jié)
? 這篇文章到這也是寫(xiě)完了,有一說(shuō)一小編這篇文章本來(lái)應(yīng)該很早就寫(xiě)完的,但是暑假末期我開(kāi)擺了,于是我拖到現(xiàn)在才寫(xiě)完,這里我得批評(píng)下自己,太懶了,所以這篇文章跨越的時(shí)間有點(diǎn)長(zhǎng),所以可能會(huì)出現(xiàn)有一些語(yǔ)言的不搭,希望各位讀者朋友理解,如果文章有錯(cuò)誤的話,可以在評(píng)論區(qū)指出,小編會(huì)及時(shí)的回復(fù),那么,我們下一篇文章見(jiàn)啦!