??? 之前一直在學(xué)習(xí)C/C++尚骄,關(guān)于const的使用,這里出現(xiàn)一點(diǎn)侵续,那里出現(xiàn)一點(diǎn)倔丈。知識(shí)用時(shí)方恨少,這一段時(shí)間正好各種筆試題询兴,其中關(guān)于const的用法也是層出不窮乃沙,所以疲于在書(shū)本上各種翻起趾,這里匯總一下诗舰,加深自己的印象的同時(shí),也方便以后查閱和學(xué)習(xí)训裆。菜鳥(niǎo)一個(gè)眶根,若有錯(cuò)誤,望指正边琉!
-
const關(guān)鍵字
常類(lèi)型是指使用類(lèi)型修飾符const說(shuō)明的類(lèi)型属百,常類(lèi)型的變量或?qū)ο蟮闹凳遣荒鼙桓碌摹2还艹霈F(xiàn)在任何上下文都是為這個(gè)目的而服務(wù)的变姨。????
-
const使用方法
-
定義const對(duì)象
const修飾符可以把對(duì)象轉(zhuǎn)變成常數(shù)對(duì)象族扰,意思就是說(shuō)利用const進(jìn)行修飾的變量的值在程序的任意位置將不能再被修改,就如同常數(shù)一樣使用!任何修改該變量的嘗試都會(huì)導(dǎo)致編譯錯(cuò)誤:
??? 注意:因?yàn)槌A吭诙ㄒ院缶筒荒鼙恍薷挠婧牵远x時(shí)必須初始化:
??????? 對(duì)于類(lèi)中的const成員變量必須通過(guò)初始化列表進(jìn)行初始化怒竿,如下所示:
- const對(duì)象默認(rèn)為文件的局部變量
在全局作用域里定義非const變量時(shí),它在整個(gè)程序中都可以訪問(wèn)扩氢,我們可以把一個(gè)非const變量定義在一個(gè)文件中,假設(shè)已經(jīng)做了合適的聲明,就可以在另外的文件中使用這個(gè)變量:
與其他變量不同晕翠,除非特別說(shuō)明盖文,在全局作用域聲明的const變量是定義該對(duì)象的文件的局部變量。此變量只存在于那個(gè)文件中双饥,不能被其他文件訪問(wèn)媒抠。通過(guò)指定const變量為extern,就可以在整個(gè)程序中訪問(wèn)const對(duì)象咏花。
注意:非const變量默認(rèn)為extern领舰。要使const變量能夠在其他文件中訪問(wèn),必須在文件中顯式地指定它為extern迟螺。
-
const 引用
const引用是指向const對(duì)象的引用:
可以讀取但不能修改refVal冲秽,因此,任何對(duì)refVal的賦值都是不合法的矩父。這個(gè)限制有其意義:不能直接對(duì)ival賦值锉桑,因此不能通過(guò)使用refVal來(lái)修改ival。同理窍株,用ival初始化ref2也是不合法的:ref2是普通的非const引用民轴,因此可以用來(lái)修改ref2指向的對(duì)象的值。通過(guò)ref2對(duì)ival賦值會(huì)導(dǎo)致修改const對(duì)象的值球订,為防止這樣的修改后裸,需要規(guī)定將普通的引用綁定到const對(duì)象是不合法的。 const 引用可以初始化為不同類(lèi)型的對(duì)象或者初始化為右值冒滩。如字面值常量:
同樣的初始化對(duì)于非const引用卻是不合法的微驶,而且會(huì)導(dǎo)致編譯時(shí)錯(cuò)誤。其原因非常微妙开睡,值得解釋一下因苹。觀察將引用綁定到不同的類(lèi)型時(shí)所發(fā)生的事情,最容易理解上述行為篇恒。對(duì)于下一段代碼:
編譯器會(huì)將這些代碼轉(zhuǎn)換為一下形式:
我們發(fā)現(xiàn)編譯器會(huì)創(chuàng)建一個(gè)int型的暫時(shí)變量存儲(chǔ)dval扶檐,然后將ri綁定到temp上。
注意:引用在內(nèi)部存放的是一個(gè)對(duì)象的地址胁艰,它是該對(duì)象的別名款筑。對(duì)于不可尋址的值智蝠,如文字常量,以及不同類(lèi)型的對(duì)象奈梳,編譯器為了實(shí)現(xiàn)引用寻咒,必須生成一個(gè)臨時(shí)對(duì)象,引用實(shí)際上指向該對(duì)象颈嚼,但用戶(hù)不能訪問(wèn)它毛秘。
如果ri不是const,那么可以給ri賦一新值阻课。這樣做不會(huì)修改dval的叫挟,而是修改了temp。期望對(duì)ri賦值會(huì)修改dval的程序員會(huì)發(fā)現(xiàn)dval沒(méi)有被修改限煞。僅允許const引用綁定到需要臨時(shí)使用的值完全避免了這個(gè)問(wèn)題抹恳,直接告訴程序員不能修改,因?yàn)閏onst引用是只讀的哈~(其實(shí)就是避免程序員心理預(yù)期產(chǎn)生反差署驻。奋献。。)
注意:非const引用只能綁定到與該引用相同類(lèi)型的對(duì)象旺上。 const引用則可以綁定到不同但相關(guān)的類(lèi)型的對(duì)象或綁定到右值瓶蚂。
- const對(duì)象的動(dòng)態(tài)數(shù)組
如果我們?cè)谧杂纱鎯?chǔ)區(qū)中創(chuàng)建的數(shù)組存儲(chǔ)了內(nèi)置類(lèi)型的const對(duì)象,則必須為這個(gè)數(shù)組提供初始化: 因?yàn)閿?shù)組元素都是const對(duì)象宣吱,無(wú)法賦值窃这。實(shí)現(xiàn)這個(gè)要求的唯一方法是對(duì)數(shù)組做值初始化。
C++允許定義類(lèi)類(lèi)型的const數(shù)組征候,但該類(lèi)類(lèi)型必須提供默認(rèn)構(gòu)造函數(shù):
-
指針和const限定符的關(guān)系(重點(diǎn):脊ァ!0贪印U捉狻!E苋唷锅睛!非常容易搞混)
const限定符和指針結(jié)合起來(lái)常見(jiàn)的情況有以下幾種。
- 指向常量的指針(指向const對(duì)象的指針)
? C++為了保證不允許使用指針改變所指的const值這個(gè)特性畔裕,強(qiáng)制要求這個(gè)指針也必須具備const特性:
這里cptr是一個(gè)指向double類(lèi)型const對(duì)象的指針衣撬,const先頂了cptr指向的對(duì)象的類(lèi)型乖订,而并非cptr本身扮饶,所以cptr本身并不是const。所以定義的時(shí)候并不需要對(duì)它進(jìn)行初始乍构,如果需要的話甜无,允許給cptr重新賦值扛点,讓其指向另一個(gè)const對(duì)象。但不能通過(guò)cptr修改其所指對(duì)象的值岂丘。
而我們將一個(gè)const對(duì)象的地址賦給一個(gè)普通的非const指針也會(huì)導(dǎo)致編譯錯(cuò)誤陵究。
不能使用void*指針保存const對(duì)象的地址,必須使用const void*類(lèi)型的指針保存const對(duì)象的地址奥帘。
下面令人頭暈的一個(gè)問(wèn)題來(lái)了----à 允許把非const對(duì)象的地址賦給指向const對(duì)象的指針铜邮,例如:
但是我們不能通過(guò)cptr指針來(lái)修改dval的值!U!松蒜!即使它指向的是非const對(duì)象。
然后已旧,我們一定要知道秸苗,不能使用指向const對(duì)象的指針修改基礎(chǔ)對(duì)象,然而如果該指針指向了非const對(duì)象运褪,可用其他方式修改其所指的對(duì)象惊楼,所以事實(shí)上,可以修改const指針?biāo)赶虻闹档慕斩铮遣荒芡ㄟ^(guò)const對(duì)象指針來(lái)進(jìn)行而已檀咙!如下所示:
通過(guò)以上,我們知道指向const對(duì)象的指針 確切的講: 自以為指向const的指針璃诀!
- 常指針(const指針)
C++中還提供了const指針——本身的值不能被修改攀芯。
??????? 我們可以從右往左把上述定義語(yǔ)句讀作"指向int型對(duì)象的const指針"。與其他const量一樣文虏,const指針的值不能被修改侣诺,這意味著不能使curErr指向其他對(duì)象。Const指針也必須在定義的時(shí)候初始化氧秘。
??????? 指針本身是const的試試并沒(méi)有說(shuō)明是否能用改真真修改其所指向的對(duì)象的值年鸳。指針對(duì)象的值能否修改完全取決于該對(duì)象的類(lèi)型。
- 指向常量的常指針(指向const對(duì)象的const指針)
如下可以這樣定義:
這樣pi_ptr首先是一個(gè)const指針丸相,然后其指向一個(gè)const對(duì)象~~~
- 函數(shù)和const限定符的關(guān)系(另一難點(diǎn)Iθ贰!灭忠!理解)
- 類(lèi)中的const成員函數(shù)(常量成員函數(shù))
在一個(gè)類(lèi)中膳算,任何不會(huì)修改數(shù)據(jù)成員的函數(shù)都應(yīng)該聲明為const類(lèi)型。如果在編寫(xiě)const成員函數(shù)時(shí)弛作,不慎修改了數(shù)據(jù)成員涕蜂,或者調(diào)用了其它非const成員函數(shù),編譯器將指出錯(cuò)誤映琳,這無(wú)疑會(huì)提高程序的健壯性机隙。使用const關(guān)鍵字進(jìn)行說(shuō)明的成員函數(shù)蜘拉,稱(chēng)為常成員函數(shù)。只有常成員函數(shù)才有資格操作常量或常對(duì)象有鹿,沒(méi)有使用const關(guān)鍵字說(shuō)明的成員函數(shù)不能用來(lái)操作常對(duì)象旭旭。常成員函數(shù)說(shuō)明格式如下:
<類(lèi)型說(shuō)明符> <函數(shù)名> (<參數(shù)表>) const;
其中葱跋,const是加在函數(shù)說(shuō)明后面的類(lèi)型修飾符持寄,它是函數(shù)類(lèi)型的一個(gè)組成部分,因此娱俺,在函數(shù)實(shí)現(xiàn)部分也要帶const關(guān)鍵字际看。下面舉一例子說(shuō)明常成員函數(shù)的特征。
- 函數(shù)重載
既然const是定義為const函數(shù)的組成部分矢否,那么就可以通過(guò)添加const實(shí)現(xiàn)函數(shù)重載咯仲闽。
其中print成員函數(shù)就實(shí)現(xiàn)了兩個(gè)版本~~~ 重載哦,輸出結(jié)果為 5,52僵朗。 const對(duì)象默認(rèn)調(diào)用const成員函數(shù)赖欣。
const修飾函數(shù)返回值其實(shí)用的并不是很多,它的含義和const修飾普通變量以及指針的含義基本相同验庙。如下所示:
- const定義的常量在超出其作用域之后其空間會(huì)被釋放温圆,而static定義的靜態(tài)常量在函數(shù)執(zhí)行后不會(huì)釋放其存儲(chǔ)空間。
- static表示的是靜態(tài)的孩革。類(lèi)的靜態(tài)成員函數(shù)岁歉、靜態(tài)成員變量是和類(lèi)相關(guān)的,而不是和類(lèi)的具體對(duì)象相關(guān)的嫉戚。即使沒(méi)有具體對(duì)象刨裆,也能調(diào)用類(lèi)的靜態(tài)成員函數(shù)和成員變量澈圈。一般類(lèi)的靜態(tài)函數(shù)幾乎就是一個(gè)全局函數(shù)彬檀,只不過(guò)它的作用域限于包含它的文件中帆啃。
- 在C++中,static靜態(tài)成員變量不能在類(lèi)的內(nèi)部初始化窍帝。在類(lèi)的內(nèi)部只是聲明努潘,定義必須在類(lèi)定義體的外部,通常在類(lèi)的實(shí)現(xiàn)文件中初始化坤学,如:double Account::Rate=2.25; static關(guān)鍵字只能用于類(lèi)定義體內(nèi)部的聲明中疯坤,定義時(shí)不能標(biāo)示為static
- 在C++中,const成員變量也不能在類(lèi)定義處初始化深浮,只能通過(guò)構(gòu)造函數(shù)初始化列表進(jìn)行压怠,并且必須有構(gòu)造函數(shù)。
- const數(shù)據(jù)成員,只在某個(gè)對(duì)象生存期內(nèi)是常量飞苇,而對(duì)于整個(gè)類(lèi)而言卻是可變的菌瘫。因?yàn)轭?lèi)可以創(chuàng)建多個(gè)對(duì)象,不同的對(duì)象其const數(shù)據(jù)成員的值可以不同布卡。所以不能在類(lèi)的聲明中初始化const數(shù)據(jù)成員雨让,因?yàn)轭?lèi)的對(duì)象沒(méi)被創(chuàng)建時(shí),編譯器不知道const數(shù)據(jù)成員的值是什么忿等。
- const數(shù)據(jù)成員的初始化只能在類(lèi)的構(gòu)造函數(shù)的初始化列表中進(jìn)行栖忠。要想建立在整個(gè)類(lèi)中都恒定的常量,應(yīng)該用類(lèi)中的枚舉常量來(lái)實(shí)現(xiàn)贸街,或者static const庵寞。
- const成員函數(shù)主要目的是防止成員函數(shù)修改對(duì)象的內(nèi)容。即const成員函數(shù)不能修改成員變量的值薛匪,但可以訪問(wèn)成員變量皇帮。當(dāng)方法成員函數(shù)時(shí),該函數(shù)只能是const成員函數(shù)蛋辈。
其中關(guān)于static属拾、const、static cosnt冷溶、const static成員的初始化問(wèn)題:
???? 在一個(gè)類(lèi)里建立一個(gè)const時(shí)渐白,不能給他初值
?????? 最后通過(guò)一個(gè)完整的例子展示以上結(jié)果: