我們已經(jīng)為類(lèi)定義了接口,但是并沒(méi)有任何機(jī)制強(qiáng)制用戶(hù)使用這些接口脾拆。
類(lèi)還沒(méi)有封裝夜惭,也就是說(shuō)用戶(hù)可以直達(dá) sales_data 對(duì)象的內(nèi)部并且控制它的具體實(shí)現(xiàn)細(xì)節(jié)。
在 C++ 中啸胧,使用訪(fǎng)問(wèn)說(shuō)明符加強(qiáng)類(lèi)的封裝性赶站。
定義在 public 說(shuō)明符之后的成員在整個(gè)程序內(nèi)可被訪(fǎng)問(wèn),public 成員定義類(lèi)的接口纺念。
定義在 private 說(shuō)明符之后的成員可以被類(lèi)的成員函數(shù)訪(fǎng)問(wèn)贝椿,但是不能被使用該類(lèi)的代碼訪(fǎng)問(wèn),private 部分封裝了類(lèi)的實(shí)現(xiàn)細(xì)節(jié)陷谱。
作為接口的一部分烙博,構(gòu)造函數(shù)和部分成員函數(shù)緊跟在 public 說(shuō)明符后,數(shù)據(jù)成員和作為實(shí)現(xiàn)部分的函數(shù)則跟在 private 說(shuō)明符后烟逊。
一個(gè)類(lèi)可以包含 0 或 多個(gè) 訪(fǎng)問(wèn)說(shuō)明符渣窜,而且對(duì)于某個(gè)訪(fǎng)問(wèn)說(shuō)明符能出現(xiàn)多少次也沒(méi)有嚴(yán)格限定。
每個(gè)訪(fǎng)問(wèn)說(shuō)明符指定了接下來(lái)的成員的訪(fǎng)問(wèn)級(jí)別宪躯,其有效范圍直到出現(xiàn)下一個(gè)訪(fǎng)問(wèn)說(shuō)明符或到達(dá)類(lèi)的結(jié)尾乔宿。
上述定義中,使用的是 class 而非 struct 開(kāi)始類(lèi)的定義访雪。僅僅是形式上有所不同详瑞,實(shí)際上我們可以使用這兩個(gè)關(guān)鍵字中的任何一個(gè)定義類(lèi)。區(qū)別僅是 struct 和 class 的默認(rèn)訪(fǎng)問(wèn)權(quán)限不太一樣臣缀。
類(lèi)可以在它的第一個(gè)訪(fǎng)問(wèn)說(shuō)明符之前定義成員坝橡,對(duì)這種成員的訪(fǎng)問(wèn)權(quán)限依賴(lài)于類(lèi)定義的方式。若使用 struct 則定義在第一個(gè)訪(fǎng)問(wèn)說(shuō)明符之前的成員是 public 精置;若使用 class 則這些成員是 privat 计寇。
既然 sales_data 的數(shù)據(jù)成員是 private 的,我們的 read、print番宁、add 函數(shù)也就無(wú)法正常編譯了蹲堂,這是因?yàn)楸M管這幾個(gè)函數(shù)是類(lèi)的接口的一部分,但不是類(lèi)的成員贝淤。
類(lèi)可以允許其它類(lèi)或者函數(shù)訪(fǎng)問(wèn)它的非公有成員柒竞,方法是令其它類(lèi)或者函數(shù)稱(chēng)為它的友元。
如果類(lèi)想把一個(gè)函數(shù)作為它的友元播聪,只要增加一條以 friend 關(guān)鍵字開(kāi)始的函數(shù)聲明語(yǔ)句即可朽基。
友元聲明只能出現(xiàn)在類(lèi)定義的內(nèi)部,但是類(lèi)內(nèi)出現(xiàn)的具體位置不限离陶。
友元不是類(lèi)的成員也不受它所在區(qū)域訪(fǎng)問(wèn)控制級(jí)別的約束稼虎。
封裝有兩個(gè)重要的有點(diǎn):
確保用戶(hù)代碼不會(huì)無(wú)意間破壞封裝對(duì)象的狀態(tài)。
被封裝的類(lèi)的具體實(shí)現(xiàn)細(xì)節(jié)可以隨時(shí)改變招刨,而無(wú)須調(diào)整用戶(hù)級(jí)別的代碼霎俩。
友元的聲明僅僅制定了訪(fǎng)問(wèn)權(quán)限,而非一個(gè)通常意義上的函數(shù)聲明沉眶。若希望類(lèi)的用戶(hù)能夠調(diào)用某個(gè)友元函數(shù)打却,那么我們就必須在友元聲明之外再專(zhuān)門(mén)對(duì)函數(shù)進(jìn)行一次聲明。
為了使友元對(duì)類(lèi)的用戶(hù)可見(jiàn)谎倔,我們通常把友元的聲明與類(lèi)本身放置在同一個(gè)頭文件中(類(lèi)的外部)