前言:類(lèi)和對(duì)象是面向?qū)ο笳Z(yǔ)言的重要概念。 c++身為一門(mén)既面向過(guò)程,又面向?qū)ο?/span>的語(yǔ)言。 想要學(xué)習(xí)c++, 首先同樣要先了解類(lèi)和對(duì)象。 本節(jié)就類(lèi)和對(duì)象的幾種構(gòu)造函數(shù)相關(guān)內(nèi)容進(jìn)行深入的解析。
目錄
類(lèi)和對(duì)象的基本概念
封裝
類(lèi)域和類(lèi)體
訪(fǎng)問(wèn)限定符
private
public
protect
默認(rèn)訪(fǎng)問(wèn)限定
成員函數(shù)與this指針
構(gòu)造函數(shù)
初始化規(guī)則?
三個(gè)必須初始化的變量類(lèi)型
默認(rèn)構(gòu)造函數(shù)
默認(rèn)成員函數(shù)
默認(rèn)構(gòu)造函數(shù)
默認(rèn)拷貝構(gòu)造函數(shù)
拷貝構(gòu)造
默認(rèn)拷貝構(gòu)造
析構(gòu)函數(shù)
析構(gòu)函數(shù)
默認(rèn)析構(gòu)函數(shù)
類(lèi)和對(duì)象的基本概念
類(lèi)是一種抽象的數(shù)據(jù)類(lèi)型。它規(guī)定了某種事物的特征(成員變量,可以理解為一種屬性,是靜態(tài)的)和行為(成員函數(shù),可以理解為動(dòng)作,是動(dòng)態(tài)的)。和c語(yǔ)言結(jié)構(gòu)體類(lèi)似, 類(lèi)可以看作這種事物的模板或者藍(lán)圖。
對(duì)象則是類(lèi)的具體實(shí)例,是具體的。擁有著類(lèi)規(guī)定的特征和行為。 我們都知道, 一個(gè)藍(lán)圖可以創(chuàng)造許多建筑。 那么一個(gè)類(lèi)也可以創(chuàng)建多個(gè)對(duì)象。并且每個(gè)對(duì)象都有著類(lèi)似的特征和行為。?
如圖就是定義的一個(gè)類(lèi),這個(gè)類(lèi)規(guī)定了事物stu有三個(gè)特征:姓名, 學(xué)號(hào), 成績(jī)。 有著一個(gè)行為:修改成績(jī)。并且將其實(shí)例化出對(duì)象p1, 此時(shí)p1有著這個(gè)類(lèi)規(guī)定的三個(gè)特征,一個(gè)行為——?p1有著自己的名字, 有著自己的學(xué)號(hào), 有著自己的成績(jī)。 同時(shí)他還能修改自己的成績(jī)。
(注:c++的小語(yǔ)法相對(duì)于c語(yǔ)言多了許多,雖然使用方便,但是剛開(kāi)始學(xué)c++也可能很難全部掌握,所以建議剛開(kāi)始學(xué)習(xí)c++的時(shí)候建議勤看看小的知識(shí)點(diǎn)。比如c向c++過(guò)渡的一些知識(shí)點(diǎn)。這樣學(xué)著會(huì)舒服很多, 不會(huì)有一種模糊的感覺(jué)。比如圖中的成員函數(shù)的知識(shí)點(diǎn)就是缺省參數(shù),這同樣是c向c++過(guò)渡的一些小知識(shí)點(diǎn)。 但是掌握不熟悉就會(huì)迷惑。不要不信,比如我問(wèn)你半缺?。╥nt x = 10, int y )這樣是否正確,你根據(jù)你心里的答案, 然后擬定傳參(1), 你看看是否正確?這個(gè)1是給誰(shuí)?如果你很懵, 那你可以在看完這篇文章后去復(fù)習(xí)它。恭喜你對(duì)這個(gè)知識(shí)點(diǎn)又加深了一點(diǎn)理解。?)
封裝
類(lèi)和對(duì)象三大特征:封裝, 繼承和多態(tài),這里講解封裝, 繼承和多態(tài)后續(xù)再說(shuō)。
首先, 封裝的概念很好理解, 就是將一個(gè)或多個(gè)特征屬性和一個(gè)或多個(gè)行為方法封裝起來(lái)。只對(duì)外公布接口。使用人通過(guò)接口操作修改對(duì)象的屬性。 封裝有利于數(shù)據(jù)的安全性和完整性。同時(shí)有利于代碼的模塊化和可維護(hù)。
圖中的student類(lèi)封裝起來(lái)了三個(gè)特征變量:name, num, grade。 一個(gè)接口函數(shù)revise_grade:
圖中private, public是訪(fǎng)問(wèn)限定符, 決定了類(lèi)的實(shí)例是否可以直接調(diào)用類(lèi)的成員。
類(lèi)域和類(lèi)體
類(lèi)域和類(lèi)體是類(lèi)和對(duì)象的兩個(gè)重要組成部分。
類(lèi)域是指類(lèi)的屬性和特性, 也就是類(lèi)的成員變量。?類(lèi)域可以是公共的(public),私有的(private)或受保護(hù)的(protected)。公共的類(lèi)域可以被類(lèi)的外部訪(fǎng)問(wèn),私有的類(lèi)域只能在類(lèi)內(nèi)部本地訪(fǎng)問(wèn)。受保護(hù)的類(lèi)域這里不解釋?zhuān)?可以看作和私有的類(lèi)域相同。
類(lèi)體是指包含在類(lèi)聲明中的代碼塊,它定義了類(lèi)的行為和功能。類(lèi)體包含了構(gòu)造函數(shù)、成員函數(shù)、成員變量,以及其他相關(guān)代碼。也就是說(shuō)類(lèi)體包含類(lèi)域。
訪(fǎng)問(wèn)限定符
訪(fǎng)問(wèn)限定符有三個(gè): private, public, protect.
private
private的意思的私有, 在private以下定義的成員不能被類(lèi)的實(shí)例直接訪(fǎng)問(wèn)到。 只能通過(guò)成員函數(shù)間接訪(fǎng)問(wèn)。?
這里可以利用成員函數(shù)revise_grade間接訪(fǎng)問(wèn)
public
public的意思是公有, public之后定義的成員可以被類(lèi)的實(shí)例訪(fǎng)問(wèn)。
?
protect
protect和private類(lèi)似, 在他們之后定義的成員都不可直接訪(fǎng)問(wèn)。
默認(rèn)訪(fǎng)問(wèn)限定
訪(fǎng)問(wèn)限定符的范圍是該訪(fǎng)問(wèn)限定符到下一個(gè)訪(fǎng)問(wèn)限定符的中間的內(nèi)容。如果下面沒(méi)有訪(fǎng)問(wèn)限定符, 那么就是之后的所有范圍。
?struct的默認(rèn)訪(fǎng)問(wèn)限定是public;
class的默認(rèn)訪(fǎng)問(wèn)限定是private。
這些記住就行。
成員函數(shù)與this指針
要理解封裝的概念, 還要理解this指針在類(lèi)中起到的作用。
類(lèi)中的成員函數(shù)默認(rèn)第一個(gè)形參都是this指針, this指針是一個(gè)關(guān)鍵詞,并且這個(gè)this指針調(diào)用該函數(shù)的對(duì)象。我們平常定義構(gòu)造函數(shù)或者成員函數(shù)是看不到定義this指針知識(shí)將this指針隱藏了。
this指針可以讓我們找到特定的對(duì)象。
構(gòu)造函數(shù)
構(gòu)造函數(shù)是類(lèi)和對(duì)象中新添的一種概念。類(lèi)在進(jìn)行實(shí)例化時(shí)會(huì)自動(dòng)調(diào)用自己的構(gòu)造函數(shù)。
如圖紅框框就是定義的一個(gè)構(gòu)造函數(shù),構(gòu)造函數(shù)的定義實(shí)現(xiàn)方式與普通函數(shù)有兩處不同:
1.構(gòu)造函數(shù)沒(méi)有返回值。
2.構(gòu)造函數(shù)有符號(hào)化列表,也就是圖中的綠框框。
符號(hào)化列表的初始化使用括號(hào)的方式, 括號(hào)中就是初始化的數(shù)值。這里三個(gè)變量分別是_name, _num, _grade, 然后通過(guò)形參name, num, grade對(duì)他們進(jìn)行賦值。
初始化規(guī)則?
下面請(qǐng)仔細(xì)閱讀。很復(fù)雜,很重要。
首先, 構(gòu)造函數(shù)的執(zhí)行方式順序是先初始化列表。再函數(shù)體。
然后,初始化列表的執(zhí)行順序不是從上到下, 而是按照成員變量的聲明順序進(jìn)行初始化。
初始化列表中沒(méi)有初始化的對(duì)象, 比如_name, 就只能等到函數(shù)體再初始化。
初始化列表對(duì)內(nèi)置類(lèi)型就是如圖中的初始化方式。注意, 是內(nèi)置類(lèi)型才是上面的方式。自定義類(lèi)型就沒(méi)有這么簡(jiǎn)單了。
首先構(gòu)造函數(shù)的執(zhí)行順序不會(huì)改變。 但是如果成員變量中有自定義類(lèi)型的話(huà),?它在初始化的時(shí)候, 會(huì)去調(diào)用自己相應(yīng)的構(gòu)造函數(shù)。 (因?yàn)閷?duì)內(nèi)置類(lèi)型編譯器可以直接進(jìn)行賦值拷貝工作。但是對(duì)于自定義類(lèi)型, 編譯器無(wú)法自己進(jìn)行復(fù)制拷貝工作。 所以只能去調(diào)用類(lèi)型本身的構(gòu)造函數(shù)。 這其實(shí)就是套娃的過(guò)程:如果調(diào)用的構(gòu)造函數(shù)中還有自定義類(lèi)型的初始化, 那么就要再去調(diào)用那個(gè)自定義類(lèi)型的構(gòu)造函數(shù),直到調(diào)用的構(gòu)造函數(shù)中沒(méi)有自定義類(lèi)型?)
-------------------------------------------------------------------------------------------------------------------------
以上, 是將自定義類(lèi)型顯示在符號(hào)化列表初始化的情況。 如果沒(méi)有在符號(hào)化列表初始化的話(huà)。?那么編譯器會(huì)自動(dòng)對(duì)該自定義類(lèi)型變量進(jìn)行初始化。并且初始化時(shí)不傳參,就是這個(gè)意思
就相當(dāng)于這里的_b進(jìn)行初始化的時(shí)候沒(méi)有傳參。
以上, 就是初始化列表對(duì)于自定義類(lèi)型以及內(nèi)置類(lèi)型初始化的規(guī)則。?
現(xiàn)在引入兩個(gè)概念, 一個(gè)概念是:三種必須在初始化列表初始化的變量類(lèi)型。?
第二個(gè)概念是:默認(rèn)構(gòu)造函數(shù)的概念。?
三個(gè)必須初始化的變量類(lèi)型
三個(gè)必須在初始化列表初始化的變量類(lèi)型:引用類(lèi)型, const修飾的常變量, 以及上面講的自定義類(lèi)型。?
那么為什么會(huì)有這樣的規(guī)定?
首先引用類(lèi)型必須在定義的時(shí)候初始化。類(lèi)的實(shí)例化的同時(shí)也是對(duì)類(lèi)的特征,屬性進(jìn)行初始化的時(shí)候。如果這一次沒(méi)有初始化。 那么之后再對(duì)類(lèi)的特征進(jìn)行處理, 那不是初始化。 那叫賦值。?
所以必須對(duì)引用類(lèi)型進(jìn)行初始化。?
至于const修飾的常變量同樣的道理, 因?yàn)楸仨氃诙x的時(shí)候初始化, 那么就必須在初始化列表初始化。 你可能有疑惑說(shuō)為什么必須在初始化列表, 在構(gòu)造函數(shù)的函數(shù)體初始化不行嗎?其實(shí), c++中規(guī)定了, 初始化列表的叫初始化, 函數(shù)體中的是賦值。?
-----------------------------------------------自定義類(lèi)型很重要--------------------------------------------------
自定義類(lèi)型為什么規(guī)定不做解釋?zhuān)?只需要知道這樣規(guī)定就好。重點(diǎn)是自定義類(lèi)型與上面兩個(gè)有點(diǎn)差異。 雖然自定義類(lèi)型也必須初始化。 但是如果我們不對(duì)它進(jìn)行初始化, 編譯器不會(huì)報(bào)錯(cuò)。 而是自己去調(diào)用自定義類(lèi)型的默認(rèn)構(gòu)造函數(shù)。 這就叫自定義類(lèi)型的隱式初始化。
-------------------------------------------------------------------------------------------------------------------------
默認(rèn)構(gòu)造函數(shù)
那么什么是默認(rèn)構(gòu)造函數(shù), 這就是我們的第二個(gè)要引入的概念:
默認(rèn)構(gòu)造函數(shù)就是:沒(méi)有形參, 或者形參全缺省的構(gòu)造函數(shù)。?
默認(rèn)成員函數(shù)
在c++的類(lèi)的成員函數(shù)中,有六個(gè)特殊的成員函數(shù), 被稱(chēng)為默認(rèn)成員函數(shù)。
默認(rèn)成員函數(shù)的意思就是如果不定義他們, 系統(tǒng)就會(huì)自動(dòng)生成。
這里主要分析三個(gè):默認(rèn)構(gòu)造函數(shù)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 默認(rèn)拷貝構(gòu)造函數(shù)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 析構(gòu)函數(shù)
默認(rèn)構(gòu)造函數(shù)
首先, 什么是默認(rèn)構(gòu)造函數(shù),這個(gè)概念在上面我們剛剛提到。 這里不做贅述。
那么編譯器生成的默認(rèn)構(gòu)造函數(shù)什么樣的?如圖:
如圖中紅框框,編譯器就會(huì)默認(rèn)生程這樣的默認(rèn)構(gòu)造函數(shù)。
由此我們可以知道。 這里生成的默認(rèn)構(gòu)造函數(shù)雖然是個(gè)空函數(shù)體, 空初始化列表。 但是通過(guò)上面的知識(shí)我們直到。 他會(huì)對(duì)自定義類(lèi)型進(jìn)行處理——自定義類(lèi)型的隱式初始化。?
所以:默認(rèn)構(gòu)造函數(shù)的作用是對(duì)內(nèi)置類(lèi)型不做任何處理。 但是對(duì)于自定義類(lèi)型會(huì)去調(diào)用它的默認(rèn)構(gòu)造函數(shù)。
如果我們定義了任意一個(gè)構(gòu)造函數(shù), 編譯器都不會(huì)生成默認(rèn)構(gòu)造函數(shù)。?
這個(gè)時(shí)候我們?nèi)绻@樣定義, 就會(huì)報(bào)錯(cuò), 因?yàn)闆](méi)有可以調(diào)用的構(gòu)造函數(shù)。?
?但是我們?nèi)绻欢x這個(gè)構(gòu)造函數(shù), 就可以編譯通過(guò), 因?yàn)榇藭r(shí)編譯器默認(rèn)生成了一個(gè)空的默認(rèn)構(gòu)造函數(shù), 不需要傳參。 可以匹配p1
?有一個(gè)好辦法就是定義全缺省的默認(rèn)構(gòu)造函數(shù), 這樣就可以一勞永逸, 不必?fù)?dān)心傳參是否有匹配的構(gòu)造函數(shù)的問(wèn)題:
默認(rèn)拷貝構(gòu)造函數(shù)
在學(xué)習(xí)默認(rèn)拷貝構(gòu)造函數(shù)之前我們要先學(xué)習(xí)拷貝構(gòu)造函數(shù)
拷貝構(gòu)造
拷貝構(gòu)造是構(gòu)造函數(shù)的一種重載形式。 它的參數(shù)是類(lèi)本身實(shí)例化對(duì)象。意思就是將已經(jīng)實(shí)例化的對(duì)象的值拷貝給將要實(shí)例化的對(duì)象。
?當(dāng)我們使用對(duì)象初始化對(duì)象的時(shí)候就會(huì)調(diào)用拷貝構(gòu)造。
默認(rèn)拷貝構(gòu)造
默認(rèn)拷貝構(gòu)造只對(duì)內(nèi)置類(lèi)型進(jìn)行淺拷貝操作。如果是涉及到動(dòng)態(tài)分配問(wèn)題。那么就達(dá)不到我們的要求。 因?yàn)榫幾g器不會(huì)對(duì)動(dòng)態(tài)內(nèi)存分配的內(nèi)存里的數(shù)據(jù)進(jìn)行拷貝。
像圖中, 只是p1的_name成員保存的地址賦值給了p2的_name成員。
但是, 這不符合我們的要求。 所以我們就不能使用默認(rèn)拷貝構(gòu)造函數(shù)。 而是需要我們自己定義拷貝構(gòu)造函數(shù)。?
像如圖中自己定義的拷貝構(gòu)造就是深拷貝。??
析構(gòu)函數(shù)
拷貝構(gòu)造一樣, 在學(xué)習(xí)默認(rèn)析構(gòu)函數(shù)之前我們應(yīng)該了解以下析構(gòu)函數(shù)。
析構(gòu)函數(shù)
析構(gòu)函數(shù)就是對(duì)空間進(jìn)行釋放。 對(duì)于內(nèi)置類(lèi)型來(lái)說(shuō), 不需要定義析構(gòu)函數(shù), 因?yàn)榫幾g器會(huì)自動(dòng)對(duì)內(nèi)置類(lèi)型進(jìn)行釋放。 但是涉及到資源分配的問(wèn)題。 編譯器無(wú)法直接對(duì)資源分配空間進(jìn)行釋放。 所以就用到了析構(gòu)函數(shù)。
析構(gòu)函數(shù)的函數(shù)名稱(chēng)是類(lèi)名前面加上~, 并且析構(gòu)函數(shù)不接受任何傳參。 同時(shí)析構(gòu)函數(shù)最多只能有一個(gè)。
默認(rèn)析構(gòu)函數(shù)
編譯器默認(rèn)生成的析構(gòu)函數(shù)就是默認(rèn)構(gòu)造函數(shù)。 默認(rèn)構(gòu)造函數(shù)的類(lèi)體是空。對(duì)于內(nèi)置類(lèi)型不做處理, 對(duì)于自定義類(lèi)型會(huì)去調(diào)用該自定義類(lèi)型的構(gòu)造函數(shù)。?
如果類(lèi)中沒(méi)有申請(qǐng)資源時(shí),析構(gòu)函數(shù)可以不寫(xiě),直接使用編譯器生成的默認(rèn)析構(gòu)函數(shù)即可;但是有資源申請(qǐng)時(shí),否則會(huì)造成資源泄漏。
如何區(qū)分改寫(xiě)不該寫(xiě)呢?其實(shí), 只要你自己定義了拷貝構(gòu)造函數(shù)的時(shí)候, 就要自己手動(dòng)定義析構(gòu)函數(shù)。 因?yàn)橹灰阕约旱亩x了拷貝構(gòu)造, 說(shuō)明就涉及到了深拷貝問(wèn)題。 深拷貝就是內(nèi)存資源分配的問(wèn)題。 就要定義析構(gòu)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-839896.html
以上就是本節(jié)的全部?jī)?nèi)容。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-839896.html
到了這里,關(guān)于【圖文結(jié)合c++】一篇文章解析c++默認(rèn)函數(shù)規(guī)則,帶你深度學(xué)習(xí)構(gòu)造函數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!