構(gòu)造函數(shù)再探

構(gòu)造函數(shù)是 C++ 類的重要組成部分括享。

當(dāng)我們定義變量時習(xí)慣立即對其進行初始化河闰,而非先定義、再賦值:

定義變量

就對象的數(shù)據(jù)成員而言锨匆,初始化和賦值也有類似的區(qū)別崭别,如果沒有構(gòu)造函數(shù)的初始值列表中顯式地初始化成員,則該成員將在構(gòu)造函數(shù)體之前執(zhí)行默認初始化恐锣。

默認初始化

當(dāng)構(gòu)造函數(shù)完成后茅主,數(shù)據(jù)成員的值相同,之前版本初始化了它的數(shù)據(jù)成員侥蒙,現(xiàn)在版本對數(shù)據(jù)成員執(zhí)行了賦值操作暗膜。

有時可以忽略數(shù)據(jù)成員初始化和賦值之間的差異。如果成員是 const 或引用鞭衩,必須將其初始化学搜。當(dāng)成員屬于某種類類型且該類沒有定義默認構(gòu)造函數(shù)時娃善,也必須將這個成員初始化。

案例

和其它常量對象或者引用一樣瑞佩,成員 ci 和 ri 都必須被初始化聚磺,因此,若沒有為它們提供構(gòu)造函數(shù)初始值的話將引發(fā)錯誤:

未提供初始值引發(fā)錯誤

隨著構(gòu)造體函數(shù)一開始執(zhí)行炬丸,初始化就完成了瘫寝,初始化 const 或者引用類型的數(shù)據(jù)成員的唯一機會就是通過構(gòu)造函數(shù)初始值。

該構(gòu)造函數(shù)的正確形式

在構(gòu)造函數(shù)初始值中每個成員只能出現(xiàn)一次稠炬,否則給同一個成員賦兩個不同的初始值有什么意義焕阿?

構(gòu)造函數(shù)初始值列表只能說明用于初始化成員的值,而不限定初始化的具體執(zhí)行順序首启。成員的初始化順序與它們在類定義中的出現(xiàn)順序一致暮屡。構(gòu)造函數(shù)初始值列表中初始值的前后位置關(guān)系不會影響實際的初始化順序。

一般來說毅桃,初始化的順序沒什么特別要求褒纲,不過如果一個成員是用另一個成員來初始化的,那么這兩個成員的初始化順序就很關(guān)鍵了钥飞。

最好用構(gòu)造函數(shù)的參數(shù)作為成員的初始值莺掠,而盡量避免使用同一個對象的其它成員。這樣的好處是可以不必考慮成員的初始化順序读宙。

使用默認實參的構(gòu)造函數(shù)

若一個構(gòu)造函數(shù)為所有參數(shù)都提供了默認實參彻秆,則它實際上也定義了默認構(gòu)造函數(shù)。

我們可以定義所謂的委托構(gòu)造函數(shù)论悴,一個委托構(gòu)造函數(shù)使用它所屬的類的其他構(gòu)造函數(shù)執(zhí)行它自己的初始化過程掖棉,或者說它把它自己的一些職責(zé)委托給了其它構(gòu)造函數(shù)。

一個委托構(gòu)造函數(shù)也有一個成員初始值的列表和一個函數(shù)體膀估。在委托構(gòu)造函數(shù)內(nèi)幔亥,成員初始值列表只有一個唯一的入口,就是類名本身察纯。和其它成員初始值一樣帕棉,類名后面緊跟圓括號括起來的參數(shù)列表,參數(shù)列表必須與類中另外一個構(gòu)造函數(shù)匹配饼记。

委托構(gòu)造函數(shù)

此類中香伴,除了一個構(gòu)造函數(shù)外其它的都委托了它們的工作,第一個構(gòu)造函數(shù)接收三個實參具则,使用這些實參初始化數(shù)據(jù)成員即纲,然后結(jié)束工作。

定義默認構(gòu)造函數(shù)零七使用三參數(shù)的構(gòu)造函數(shù)完成初始化過程博肋,它也無須執(zhí)行其它任務(wù)低斋,這一點從空的構(gòu)造函數(shù)體能看的出來蜂厅。接受一個 string 的構(gòu)造函數(shù)同樣委托給了三參數(shù)的版本。

接受 istream& 的構(gòu)造函數(shù)也是委托構(gòu)造函數(shù)膊畴,它委托給了默認構(gòu)造函數(shù)掘猿,默認構(gòu)造函數(shù)又接著委托給三參數(shù)構(gòu)造函數(shù)。當(dāng)這些委托的構(gòu)造函數(shù)執(zhí)行完后唇跨,接著執(zhí)行 istream& 構(gòu)造函數(shù)體的內(nèi)容稠通。調(diào)用 read 函數(shù)讀取給定的 istream 。

當(dāng)一個構(gòu)造函數(shù)委托給另一個構(gòu)造函數(shù)時买猖,受委托的構(gòu)造函數(shù)的初始值列表和函數(shù)體被一次執(zhí)行改橘。在 sales_data 類中,受委托的構(gòu)造函數(shù)體恰好時空的政勃。膠乳函數(shù)體包含代碼的話唧龄,將先執(zhí)行這些代碼,然后控制權(quán)才會交還給委托者的函數(shù)體奸远。

當(dāng)對象被默認初始化或值初始化時自動執(zhí)行默認構(gòu)造函數(shù)。

默認初始化

類必須包含一個默認構(gòu)造函數(shù)以便在上述情況下使用讽挟,其中的大多數(shù)情況非常容易判斷懒叛。

不那么明顯的一種情況時類的某些數(shù)據(jù)成員缺少默認構(gòu)造函數(shù)。


可以正常編譯的 obj 聲明

但使用時耽梅,編譯器將報錯薛窥,提示我們不能對函數(shù)使用成員訪問運算符。盡管想聲明一個默認初始化對象眼姐, obj 實際的含義卻是一個不接受任何參數(shù)的函數(shù)并且其返回值是 sales_data 類型的對象诅迷。

如果想定義一個使用默認構(gòu)造函數(shù)進行初始化的對象,正確的方法是去掉對象名之后的空括號众旗。

正確案例
案例 2

我們可以為類定義隱式轉(zhuǎn)換規(guī)則

如果構(gòu)造函數(shù)只接受一個實參罢杉,則它實際上定義了轉(zhuǎn)換為此類類型的隱式轉(zhuǎn)換機制,有時我們把這種構(gòu)造函數(shù)稱作轉(zhuǎn)換構(gòu)造函數(shù)贡歧。

能通過一個實參調(diào)用的構(gòu)造函數(shù)定義了一條從構(gòu)造函數(shù)的參數(shù)類型向類型隱式轉(zhuǎn)換的規(guī)則滩租。

在 sales_data 類中,接受 string 的構(gòu)造函數(shù)和接受 istream 的構(gòu)造函數(shù)分別定義了從這兩種類型向 sales_data 隱式轉(zhuǎn)換的規(guī)則利朵。在需要使用 sales_data 的地方律想,我們可以使用 string 、 istream 作為替代绍弟。

編譯器指揮自動地執(zhí)行一步類型轉(zhuǎn)換

案例

是否需要從 string 到 sales_data 的轉(zhuǎn)換依賴于我們對用戶使用該轉(zhuǎn)換的看法技即。

在要求隱式轉(zhuǎn)換的程序上下文中,我們可以通過將構(gòu)造函數(shù)聲明為? explicit 加以阻止

案例

此時樟遣,沒有任何構(gòu)造函數(shù)能用于隱式地創(chuàng)建 sales_data 對象而叼,之前的兩種用法都無法通過編譯身笤。

編譯錯誤

關(guān)鍵字 explicit 只對一個實參的構(gòu)造函數(shù)有效。需要多個實參的構(gòu)造函數(shù)不能用于執(zhí)行隱式轉(zhuǎn)化澈歉,所以無須將這些構(gòu)造函數(shù)指定為 explicit 展鸡。

只能在類內(nèi)聲明構(gòu)造函數(shù)時使用 explicit ,在外部定義時不應(yīng)重復(fù)埃难。

發(fā)生隱式轉(zhuǎn)換的一種情況時當(dāng)執(zhí)行拷貝形式的初始化時 ( = )莹弊,我們只能使用直接初始化而不能使用 explicit 構(gòu)造函數(shù)。

編譯器不會將 explicit 的構(gòu)造函數(shù)用于隱式轉(zhuǎn)換過程涡尘,但是我們可以使用這樣的構(gòu)造函數(shù)顯示地強制進行轉(zhuǎn)換

案例

第一個調(diào)用中忍弛,直接使用 sales_data 的構(gòu)造函數(shù),該調(diào)用通過接受 string 的構(gòu)造函數(shù)創(chuàng)建了一個臨時的 sales_data 對象考抄。

第二個調(diào)用中细疚,使用 static_cast 執(zhí)行了顯式的而非隱式的轉(zhuǎn)換。其中川梅,static_cast 使用 istream 構(gòu)造函數(shù)創(chuàng)建了一個臨時的sales_data 對象疯兼。

部分標(biāo)準(zhǔn)庫中的類含有單參數(shù)的構(gòu)造函數(shù)

聚合類使得用戶可以直接訪問其它成員,并且具有特殊的初始化語法形式贫途。

滿足以上條件為聚合類
聚合類

我們可以提供一個花括號括起來的成員初始值列表吧彪,并用它初始化聚合類的數(shù)據(jù)成員

案例

初始值的順序必須與聲明的順序一致。

與初始化數(shù)組元素的規(guī)則一樣丢早,如果初始值列表中的元素個數(shù)少于類的成員數(shù)量姨裸,則靠后的成員被值初始化。初始值列表的元素個數(shù)絕對不能超過類的成員數(shù)量怨酝。

顯式初始化類的對象成員的缺點

除了算術(shù)類型傀缩、引用和指針外,某些類也是字面值類型农猬。

字面值類型的類可能含有 constexpr 函數(shù)成員赡艰,這樣的成員必須符合 constexpr 函數(shù)的所有要求,他們是隱式 const 的盛险。

數(shù)據(jù)成員都是字面值類型的聚合類時字面值常量類瞄摊。若類不是一個聚合類钾恢,但它符合下述要求没炒,則也是一個字面值常量類醋闭。

字面值常量類

盡管構(gòu)造函數(shù)不能時 const 的属百,但字面值常量類的構(gòu)造函數(shù)可以時 constexpr 函數(shù)茅信,一個字面值常量類必須至少提供一個 constexpr 構(gòu)造函數(shù)枯芬。

constexpr 構(gòu)造函數(shù)可以聲明成 =default 的形式掘殴。否則 constexpr 構(gòu)造函數(shù)就必須即符合構(gòu)造函數(shù)的要求匕荸,又符合 consrexpr 函數(shù)的要求。所以 constexpr 構(gòu)造函數(shù)體一般是空的祟牲。

通過前置關(guān)鍵字 constexpr 聲明 constexpr 構(gòu)造函數(shù)

constexpr 構(gòu)造函數(shù)必須初始化所有數(shù)據(jù)成員隙畜,初始值或者使用 constexpr 構(gòu)造函數(shù)或是一條常量表達式。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末说贝,一起剝皮案震驚了整個濱河市议惰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乡恕,老刑警劉巖言询,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異傲宜,居然都是意外死亡运杭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門函卒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辆憔,“玉大人,你說我怎么就攤上這事报嵌∈郑” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵锚国,是天一觀的道長彤钟。 經(jīng)常有香客問我,道長跷叉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任营搅,我火速辦了婚禮云挟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘转质。我一直安慰自己园欣,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布休蟹。 她就那樣靜靜地躺著沸枯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赂弓。 梳的紋絲不亂的頭發(fā)上绑榴,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音盈魁,去河邊找鬼翔怎。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赤套。 我是一名探鬼主播飘痛,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼容握!你這毒婦竟也來了宣脉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤剔氏,失蹤者是張志新(化名)和其女友劉穎塑猖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體介蛉,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡萌庆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了币旧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片践险。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吹菱,靈堂內(nèi)的尸體忽然破棺而出巍虫,到底是詐尸還是另有隱情,我是刑警寧澤鳍刷,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布占遥,位于F島的核電站,受9級特大地震影響输瓜,放射性物質(zhì)發(fā)生泄漏瓦胎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一尤揣、第九天 我趴在偏房一處隱蔽的房頂上張望搔啊。 院中可真熱鬧,春花似錦北戏、人聲如沸负芋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旧蛾。三九已至,卻和暖如春蠕嫁,著一層夾襖步出監(jiān)牢的瞬間锨天,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工拌阴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绍绘,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像陪拘,于是被迫代替她去往敵國和親厂镇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容