日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

对象 普通po转_谈谈C++对象的构造

發(fā)布時(shí)間:2024/10/8 c/c++ 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 对象 普通po转_谈谈C++对象的构造 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

造化從來自有神

如何對此亦無塵

平生出處皆非妄

老去功名始見真

這是小編以“構(gòu)造對象”為主題讓九歌同學(xué)創(chuàng)作的七言絕句。九歌同學(xué)以一種非常玄妙的文風(fēng)向我們介紹了對象的構(gòu)造,但這似乎并不是我們想要的答案。那么我們每次碼代碼都在進(jìn)行的“對象構(gòu)造”究竟是怎樣一回事呢?就讓小編帶領(lǐng)大家來了解一下吧!

什么是對象的構(gòu)造?

對象的構(gòu)造過程就是對象的創(chuàng)建過程。在對象構(gòu)造的過程中,我們需要進(jìn)行對象數(shù)據(jù)成員的初始化,因此對象構(gòu)造的關(guān)鍵問題就是要解決對象的成員如何初始化的問題。

C++中是如何解決對象成員初始化問題的?

我們可以對照著C語言中結(jié)構(gòu)體數(shù)據(jù)成員初始化的解決方案來看。

假定我們有如下的結(jié)構(gòu)體:

C語言的程序員們有兩種對其進(jìn)行初始化的方法。

其一是順序初始化:

其二是指定初始化:

我們可以注意到,使用順序初始化方法往往不夠靈活,需要逐一列出所有成員的初始值;而指定初始化法不被很多C++編譯器兼容,例如小編使用的Visual Studio就不兼容這種寫法,會報(bào)錯(cuò)。

在C++中,由于成員函數(shù)的引入,我們可以在類中定義一個(gè)成員函數(shù)用來進(jìn)行類的初始化。但這樣會帶來一個(gè)問題,假如在對象被創(chuàng)建之后我們忘記調(diào)用這個(gè)成員函數(shù),那么對象數(shù)據(jù)成員的值將是不確定的,對于一個(gè)大型的工程來說,這可能造成很大的麻煩。這是由于對象的創(chuàng)建以及成員的初始化分離了。此外,對于一些必須進(jìn)行初始化的成員,例如const類型和引用類型的成員,它們的初始化需要和對象同步進(jìn)行,這種先創(chuàng)建對象在初始化成員的做法也會帶來問題。

構(gòu)造函數(shù)——千呼萬喚始出來

?? 構(gòu)造函數(shù)的一般特征

構(gòu)造函數(shù)是一類特殊的成員函數(shù)。相較于一般的成員函數(shù),構(gòu)造函數(shù)有這樣兩個(gè)顯著的特征:

1、所有構(gòu)造函數(shù)都沒有返回類型的聲明;

2、構(gòu)造函數(shù)僅在對象被創(chuàng)建時(shí)被調(diào)用。

我們來看一個(gè)最簡單的構(gòu)造函數(shù)的例子:

在這個(gè)例子中,構(gòu)造函數(shù)被調(diào)用時(shí),會首先創(chuàng)建A這個(gè)對象(此時(shí)a中的數(shù)據(jù)成員尚未被賦值),然后執(zhí)行構(gòu)造函數(shù)的函數(shù)體,將A的數(shù)據(jù)成員a賦值為1,并輸出相關(guān)語句。我們可以觀察到構(gòu)造函數(shù)的一些基本特征:沒有返回類型的聲明,且函數(shù)名稱與類名相同。

  • 多種類型的構(gòu)造函數(shù)

C++中對象被創(chuàng)建的方式是多種多樣的,因此構(gòu)造函數(shù)的形式也是多種多樣的。接下來就讓我們看一看為了完成對象創(chuàng)建這個(gè)任務(wù),都有哪些類型的構(gòu)造函數(shù)吧!

默認(rèn)構(gòu)造函數(shù):

當(dāng)且僅當(dāng)類中沒有定義構(gòu)造函數(shù)時(shí),編譯器會提供一個(gè)默認(rèn)的構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)沒有參數(shù),并且函數(shù)體也是空的。在上面的例子中,這個(gè)構(gòu)造函數(shù)就類似于:Test(){};

無參構(gòu)造函數(shù):

上面講到的默認(rèn)構(gòu)造函數(shù)就是一種無參構(gòu)造函數(shù)。需要注意的是,如果參數(shù)表中的形參均具有默認(rèn)值,此時(shí)我們也可以將它當(dāng)做無參的構(gòu)造函數(shù)來調(diào)用:

有參構(gòu)造函數(shù):

我們通過一個(gè)例子來感受一下有參構(gòu)造函數(shù)的使用以及初始化列表的作用。

在這個(gè)例子中,我們聲明的類Test有三個(gè)數(shù)據(jù)成員,其中有一個(gè)是引用成員,一個(gè)是const類型的成員,這兩種類型的數(shù)據(jù)成員在定義時(shí)就必須進(jìn)行初始化,因此我們不能在構(gòu)造函數(shù)的函數(shù)體內(nèi)將它們初始化,而應(yīng)當(dāng)在初始化列表中將它們初始化,這是因?yàn)樵诔跏蓟斜碇羞M(jìn)行的初始化工作是在對象創(chuàng)建完成之前進(jìn)行的,而在函數(shù)體中進(jìn)行初始化是在對象創(chuàng)建之后進(jìn)行的。

一般來說聲明了帶參數(shù)的構(gòu)造函數(shù)之后我們最好還要定義一個(gè)默認(rèn)構(gòu)造函數(shù),以防止系統(tǒng)編譯時(shí)出錯(cuò)。

拷貝構(gòu)造函數(shù)——我來組成一支大軍!

?為什么需要拷貝構(gòu)造函數(shù)?

對于普通類型的變量而言,變量的復(fù)制是容易的,利用一個(gè)變量來初始化一個(gè)新變量也是容易的:

但正如對象的創(chuàng)建需要構(gòu)造函數(shù)一樣,對象內(nèi)部因?yàn)橛懈鞣N成員變量,其復(fù)制過程也比普通的變量要復(fù)雜,因此通過復(fù)制的方法使用一個(gè)對象去初始化另一個(gè)對象就需要用到拷貝構(gòu)造函數(shù)。

我們看一個(gè)簡單的例子:

在這個(gè)例子中,以“const Test& t”為參數(shù)的函數(shù)就是一個(gè)簡單的拷貝構(gòu)造函數(shù)??截悩?gòu)造函數(shù)的一般特征是:

1、參數(shù)中必須含有本類對象的一個(gè)引用,可以含有其他參數(shù),但這些參數(shù)必須有默認(rèn)值;

2、函數(shù)名與類名相同,且沒有返回類型的聲明。

因?yàn)槭褂昧艘?#xff0c;且拷貝構(gòu)造函數(shù)一般不希望改變被復(fù)制的對象,因此我們往往在這個(gè)參數(shù)前加上“const”修飾符。

  • 拷貝構(gòu)造函數(shù)的調(diào)用時(shí)機(jī)

拷貝構(gòu)造函數(shù)在下3種情況下會被調(diào)用:

1、用類的對象初始化類的另一個(gè)對象:在上面舉出的例子中我們可以看到,當(dāng)執(zhí)行

Test B=A;

時(shí),拷貝構(gòu)造函數(shù)會被調(diào)用。此外,如果我們把這個(gè)語句改寫成:

Test B(A);

拷貝構(gòu)造函數(shù)也會被調(diào)用。這兩種寫法執(zhí)行的操作完全相同。

2、某個(gè)函數(shù)的形參是類的對象,當(dāng)這個(gè)函數(shù)被調(diào)用,進(jìn)行形實(shí)結(jié)合時(shí)也會調(diào)用拷貝構(gòu)造函數(shù):

當(dāng)調(diào)用函數(shù) f(Test a) 時(shí),會調(diào)用Test類的拷貝構(gòu)造函數(shù)。只有參數(shù)使用值傳遞時(shí)才會調(diào)用拷貝構(gòu)造函數(shù),使用引用傳遞則不會,因此在傳遞較大的對象時(shí),一般采用引用傳遞的策略。

3、函數(shù)的返回值是類的對象,在返回值時(shí)會調(diào)用拷貝構(gòu)造函數(shù)。例如:

在這個(gè)例子中,執(zhí)行語句

b=f(A);

時(shí),當(dāng)傳遞參數(shù)時(shí)拷貝構(gòu)造函數(shù)不會被調(diào)用(因?yàn)槭褂玫氖且脗鬟f),但函數(shù)返回對象時(shí)拷貝構(gòu)造函數(shù)會被調(diào)用。

  • 深拷貝和淺拷貝

當(dāng)我們定義一個(gè)類時(shí),系統(tǒng)一般會給出一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)可以實(shí)現(xiàn)成員對象簡單的一一復(fù)制。如果成員中沒有動態(tài)成員的話,這個(gè)一一復(fù)制的結(jié)果就是我們想要的,但如果成員中有一個(gè)指針指向了一片動態(tài)開辟的存儲空間,使用系統(tǒng)默認(rèn)的拷貝構(gòu)造函數(shù)就會出現(xiàn)問題:

假設(shè)我們定義的類Test中有一個(gè)指針變量p,且我們先創(chuàng)建了一個(gè)對象A。A中的指針p在對象使用的過程中指向的是一片動態(tài)開辟的存儲空間,那么在我們執(zhí)行語句

Test B=A;

時(shí),B中的指針p也會指向同一片存儲空間。

假設(shè)我們在析構(gòu)函數(shù)的函數(shù)體中試圖釋放這片存儲空間,那么由于B和A中的指針p指向了同一片空間,而同一片空間不可以被釋放兩次,系統(tǒng)就會報(bào)錯(cuò)。(關(guān)于析構(gòu)函數(shù)的內(nèi)容,可以參考文章的下一部分)

同樣的,假如B和A的指針指向的存儲空間是一樣的,那么A.p指向的內(nèi)容改變的話,B.p指向的內(nèi)容也會被改變,這顯然不是我們想要的。

因此我們想要實(shí)現(xiàn)的是,拷貝過程中,A和B中的動態(tài)變量指向的內(nèi)容相同,但指針值本身不同。這就是所謂的“深拷貝”。

我們可以考慮以下的方式來定義一個(gè)深拷貝函數(shù):

在這個(gè)例子中,拷貝構(gòu)造函數(shù)的函數(shù)體使得復(fù)制出來的對象的指針p指向的內(nèi)容與被復(fù)制對象的指針p指向的內(nèi)容一致,但兩者本身指向的存儲空間是不同的,也就實(shí)現(xiàn)了深拷貝。

~析構(gòu)函數(shù)——我有神奇小尾巴~

?初識析構(gòu)函數(shù)

類的析構(gòu)函數(shù),它是類的一個(gè)成員函數(shù),名字由波浪號加類名構(gòu)成,是執(zhí)行與構(gòu)造函數(shù)相反的操作:釋放對象使用的資源,并銷毀非static成員。

析構(gòu)函數(shù)有這樣幾個(gè)特征:

1.函數(shù)名是在類名前加上~,無參數(shù)且無返回值,因此析構(gòu)函數(shù)不能重載。

2.一個(gè)類只能有且有一個(gè)析構(gòu)函數(shù),如果沒有顯式的定義,系統(tǒng)會生成一個(gè)缺省的析構(gòu)函數(shù)。

我們看一個(gè)簡單的析構(gòu)函數(shù)的例子:

在討論構(gòu)造函數(shù)時(shí)我們提到過,構(gòu)造函數(shù)的函數(shù)體是在對象初始化完成之后執(zhí)行的,這也是某些數(shù)據(jù)類型的成員不能通過函數(shù)體進(jìn)行初始化的原因。與構(gòu)造函數(shù)相反,析構(gòu)函數(shù)的函數(shù)體是在對象被銷毀前執(zhí)行的,并且成員的銷毀順序也是與初始化的順序相反的。

  • 釋放資源?

我們知道析構(gòu)函數(shù)的作用是銷毀不再使用的對象(好殘忍),釋放系統(tǒng)資源,那么析構(gòu)函數(shù)是怎么做到這一點(diǎn)的呢?

其實(shí)小編也不知道 如果是對象中非指針類型的成員,那么在執(zhí)行析構(gòu)函數(shù)之后,這些成員占用的內(nèi)存空間會被釋放;但有一類情形是,假如對象中有指針類型的成員,并且它指向的是一塊動態(tài)開辟的存儲空間,那么這塊空間必須由我們手動釋放,也就是說需要在析構(gòu)函數(shù)的函數(shù)體中釋放這塊存儲空間。

小編弱語

關(guān)于對象的構(gòu)造和析構(gòu),其實(shí)還有很多可聊的,但由于小編實(shí)力有限,暫時(shí)只能和大家聊這么多啦!最后,獻(xiàn)上九歌同學(xué)的一首五言絕律詩《你在哪里啊,我的對象》,向大家告別~

你在哪里啊,我的對象?

九歌

一自傷春眼,無人識此心
山林隨日轉(zhuǎn),云雨隔年沉
世路皆新鬼,浮生付亂禽
憑君莫剪伐,吾已負(fù)初音

文字 | 周航

審核|劉政寧

指導(dǎo)老師|李超

總結(jié)

以上是生活随笔為你收集整理的对象 普通po转_谈谈C++对象的构造的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。