C++ 類的其他特性
這一章我們將介紹類型成員、類的成員的類內(nèi)初始值、可變數(shù)據(jù)成員、內(nèi)聯(lián)成員函數(shù)、從成員函數(shù)返回*this、如何定義并使用類類型及友元類。
類成員再探
為了展示這些新特性,我們需要定義一對相互關(guān)聯(lián)的類,它們分別是Screen和window_mgr。
定義一個類型成員
screen表示顯示器中的一個窗口,每個screen包含一個用于保存screen內(nèi)容的string成員和三個size_type類型成員,分別用于表示光標(biāo)的位置、屏幕的高和寬。
Screen類的成員函數(shù)
要是我們的類更加實(shí)用,還需要調(diào)價一個構(gòu)造函數(shù)令用戶能夠自定義屏幕的尺寸和內(nèi)容,以及其它兩個成員,分別負(fù)責(zé)移動光標(biāo)和讀取給定位置的字符。
第二個構(gòu)造器中為cursor成員隱式的使用了類內(nèi)初始值,如果類中不存在cursor的類內(nèi)初始值,我們就需要想其他成員一樣顯式的初始化cursor。
這里我們可以看出成員函數(shù)也可以被重載。
令成員作為內(nèi)聯(lián)函數(shù)
定義在類內(nèi)部的成員函數(shù)是自動inline的,因此Screen的構(gòu)造函數(shù)和返回光標(biāo)所指字符的get函數(shù)默認(rèn)是inline函數(shù)。
我們也可以在類的外部使用inline修飾函數(shù)定義
注意:inline成員函數(shù)也應(yīng)該與相應(yīng)的類定義在同一個頭文件中。
可變數(shù)據(jù)成員
我們可以在變量聲明時加入mutable關(guān)鍵字,這樣即使這個變量處于const成員函數(shù)內(nèi),我們依舊可以修改他。
盡管some_member是一個const成員函數(shù),他依然可以改變access_ctr的值,該成員是個可變成員,因此任何成員函數(shù)包括const函數(shù)在內(nèi)都能改變他的值。
類數(shù)據(jù)成員的初始值
我們繼續(xù)定義一個窗口管理類來表示顯示器的一組Screen,這個類將包含一個Screen類型的vector,每個元素表示一個特定的Screen。默認(rèn)情況下,我們希望Window_mgr類開始時總是擁有一個默認(rèn)初始化的Screen。在C++11標(biāo)準(zhǔn)中,最好的方式就是把這個默認(rèn)值聲明成一個類內(nèi)初始值
當(dāng)我們初始化類的成員時,需要為構(gòu)造函數(shù)傳遞一個符合成員類型的實(shí)參,上面我們使用一個單獨(dú)的元素值對vector成員執(zhí)行了列表初始化,這個Screen的值被傳給vector<Screen>的構(gòu)造函數(shù)。
注意:當(dāng)我們提供一個類內(nèi)初始值時,必須以符號=或花括號表示。
返回*this的成員函數(shù)
接下來我們添加一些函數(shù),他們負(fù)責(zé)設(shè)置光標(biāo)所在位置的字符或者其他任意給定位置的字符。
我們使用set成員的返回值是set的對象的引用,返回引用的函數(shù)是左值,意味著這些函數(shù)返回的是對象本身而不是副本。
的所有操作都執(zhí)行在同一個對象上,等價于
如果我們令move和set的返回值是Screen而不是引用,等價于
從const成員函數(shù)返回this
我們繼續(xù)添加一個名為display的操作,他打印Screen的內(nèi)容,它類似于move和set,display函數(shù)也能返回執(zhí)行對象的引用。
邏輯上我們只是打印這個對象,并不需要改變,所以我們令display為一個const成員,此時this指針將是指向const的指針,*this對象是const對象,所以display的返回類型應(yīng)該是const Sales_data&,這樣我們就不能把進(jìn)行改變值的操作
基于const的重載
因?yàn)榉浅A堪姹镜暮瘮?shù)對于常量對象是不可用的,所以我們只能在一個常量對象上調(diào)用const成員函數(shù),另一方面,雖然可以在非常量對象上調(diào)用常量版本或非常量版本,但是顯然此時非常量版本是一個更好的匹配
當(dāng)一個成員調(diào)用另一個成員時,this指針在其中隱式的傳遞,因此當(dāng)display調(diào)用do_display時,他的this指針隱式的傳遞給do_display,而當(dāng)display的非常量版本調(diào)用do_display時,他的this指針將隱式的從指向非常量的指針轉(zhuǎn)換為常量指針。
do_display完成后,都會返回調(diào)用對象。
類類型
每個類定義了唯一的類型,即使他們的成員完全一樣,這兩個類也是不同類型。
對于一個類來說他的成員和其他任何類的成員都不是一回事。
類的聲明
我們可以僅聲明類而暫時不定義,這種聲明有時候稱為前向聲明,在他聲明之后定義之前是一個不完全類型,也就是說我們只知道他是一個類,卻不明白他包含那些成員。
對于一個類,我們創(chuàng)建它的對象前他必須被定義,否則編譯器無法了解這樣的對象需要多少空間。
后面我們會講述一種例外,直到被定義后數(shù)據(jù)成員才能被聲明成這種類型。
友元再探
類可以把其他類或者其他的類的成員函數(shù)定義為友元。
類之間的友元關(guān)系
如果我們的window_mgr類想訪問他管理的Screen類的內(nèi)部數(shù)據(jù)。這樣我們可以把window_mgr定義為Screen的友元
這樣window_mgr就能訪問Screen的私有成員。
如果clear不是Screen的友元,上面代碼無法通過編譯,因?yàn)閏lear無法訪問height、width和contents等成員。
注意:友元沒有傳遞性,Window_mgr的友元不是Screen的友元。
令成員函數(shù)作為友元
當(dāng)把一個成員函數(shù)作為友元時,必須聲明是哪個類的成員函數(shù)
想要某個成員函數(shù)作為友元我們必須按照如下方式設(shè)計(jì)程序
1首先定義Window_mgr類,其中聲明clear函數(shù),但是不能定義,在clear使用Screen成員之前必須先聲明Screen。
2接下來定義Screen,包括對clear的友元聲明
3最后定義clear,此時他才可以使用Screen的成員。
友元聲明和作用域
類和非成員函數(shù)的聲明不是必須在他們的友元聲明之前,當(dāng)一個名字第一次出現(xiàn)在一個友元聲明中時,我們隱式的假定改名字在當(dāng)前作用域是可見的,然而友元本身不一定真的聲明在當(dāng)前作用域中。
甚至就算在類的內(nèi)部定義該函數(shù),我們也必須在類的外部提供聲明,從而讓函數(shù)可見。
友元聲明的作用是影響訪問權(quán)限的,他本身并不是聲明。