【正文】
類前綴“R” 在這里代表資源(Resource), 通常是外部資源,例如:文件的句柄(handle)。 R類通常也有對(duì)應(yīng)的Close()或Reset()類,用來(lái)釋放資源,重置句柄的值表明沒有資源和該對(duì)象關(guān)聯(lián)。它通常也沒有析構(gòu)方法,資源的釋放都是在Close()方法中進(jìn)行的。如果一個(gè)R類是一個(gè)堆上的自動(dòng)變量(相對(duì)于成員變量),您一但要保證資源被釋放,而且,變量本身也要被釋放。 M 類當(dāng)提到多繼承的時(shí)候,它意味著從一個(gè)主要的類派生,同時(shí)也混雜基它類的功能。M類也可以被其它類繼承。class MDomesticAnimal : public MAnimal{ public: virtual void NameL() =0。 // 從 MDomesticAnimal繼承 // Other functions omitted for clarity}。但它可以有析構(gòu)方法, 條件是,實(shí)現(xiàn)它的具體類必須是從CBase派生的。 //正確然下面的代碼卻是錯(cuò)誤的。將MAnimal的代碼改寫,則上面代碼沒有問(wèn)題。}。關(guān)鍵是,它們的特殊設(shè)計(jì)使得它們?cè)谏倭績(jī)?nèi)存的設(shè)備上非常有效率,僅用非常少的內(nèi)存就可以保存自己的長(zhǎng)度和內(nèi)存布局的信息。它們不同于標(biāo)準(zhǔn)C++中的string,java語(yǔ)言中的string類或MFC中的CString,因?yàn)槌绦騿T必須自己管理底層的內(nèi)存分配和清除工作。Symbian系統(tǒng)現(xiàn)在支持這兩種字符長(zhǎng)度的描述符,除了Copy()和Size()兩個(gè)方法以外,這兩種寬度的描述符的行為是完全一致的,這兩個(gè)方法的使用,我們后面再介紹。 對(duì)中立(neutral)的類型來(lái)講,沒有數(shù)字結(jié)尾(例如:TPtr),在Symbian系統(tǒng)第5版以后,默認(rèn)的情況下,它們表示寬度為16bit的字符串。所謂字面量是指在編碼的時(shí)候就已經(jīng)確定的量,例如,標(biāo)準(zhǔn)C中的 char* p = Hello world。在Symbian系統(tǒng)中描述符類型有兩大種類:不可修改(nonmodifiable)的描述符和可修改(modifiable)的描述符。所以,Length()方法沒有被它的子類重寫,它對(duì)所有子類都有效。存放長(zhǎng)度的4個(gè)字節(jié)中,28bit用來(lái)表示長(zhǎng)度,剩下的4bit用來(lái)表示描述符的類型。后面,為了表述上的方便,我們也把這種不可修改的描述符也稱為常量描述符(constant descriptor)總結(jié):不可修改的描述符類TDesC是所有的非字面量描述符的基類,它提供了確定描述符長(zhǎng)度和訪問(wèn)數(shù)據(jù)的方法,另外,它實(shí)現(xiàn)了所有的您想用來(lái)處理常量字符串的操作。像TDesC中的Length()方法一樣,MaxLength()方法也不被TDes的子類繼承。當(dāng)然,只要不超過(guò)描述符的最大存儲(chǔ)容量,描述符的長(zhǎng)度可以自由地伸縮。事實(shí)上,不可能使描述符溢出,這一點(diǎn)保證了您代碼的強(qiáng)壯性,而且不易產(chǎn)生難以跟蹤的內(nèi)存陷阱。 前面,我們已經(jīng)解釋過(guò)為什么每個(gè)類會(huì)有三個(gè)不同的版本,例如:TDes8, TDes16 和 TDes,分別對(duì)應(yīng)窄字符,寬字符和中立的類。與指針描述符不同,緩存區(qū)描述符本身持有字符數(shù)據(jù),也就是說(shuō)字符數(shù)據(jù)本身構(gòu)成了描述符的一部分。指針描述符所持有的字符串是跟描述符本身分開來(lái)存放的,它可以被存儲(chǔ)在ROM中,堆中或棧中。在不可修改的描述符(TPtrC)中,指向數(shù)據(jù)的指針存放在長(zhǎng)度的后面,因此,指針描述符的總長(zhǎng)度為2個(gè)字(word);在可修改的指針描述符中,它存放在最大長(zhǎng)度的后面,因此,總長(zhǎng)度為3個(gè)字。所有的從基類TDesC中繼承的操作都是可訪問(wèn)的。 // 從字面量描述符構(gòu)造TPtrC copyPtr(pangramPtr)。 // 從以0結(jié)尾的字符串構(gòu)造TPtrC8 anotherPtr(cString)。 // 從一個(gè)指針構(gòu)造。_LIT(KLiteralDes2, Waltz, bad nymph, for quick jigs vex)。 // alpha points to the data in KLiteralDes2(KLiteralDes1)。 TPtrTPtr 是可修改的指針描述符,它可用來(lái)訪問(wèn)和修改字符串或二進(jìn)制數(shù)據(jù)。一個(gè)TPtr對(duì)象可以從其它的可修改描述符構(gòu)造,例如:通過(guò)在不可修改的描述符上調(diào)用Des()方法,這個(gè)方法返回一個(gè)如下所示的TPtr對(duì)象:_LIT(KLiteralDes1, Jackdaws love my big sphinx of quartz)。 can modify the data in bufTInt length = ()。 // Length of data to be representedTInt maxLen = 32。如果要拷貝的數(shù)據(jù)的長(zhǎng)度超過(guò)了描述符的最大長(zhǎng)度,會(huì)引發(fā)一個(gè)系統(tǒng)異常。 // TBufC are described laterTPtr ptr(())。 // length = 12, max length = 40// Copy and replacememPtr = ptr。 // Points to the data in buf// Replace what ptr points to(ptr2)。 基于棧(stackbased)的緩沖區(qū)描述符基于緩沖區(qū)的描述符也可以分為可修改的TBuf和不可修改TBufC的兩種類型。216。也允許創(chuàng)建一個(gè)空的描述符,然后再填充。 // Constructed from literal descriptorTBufC50 buf2(buf1)。 // buf4 contains data copied from buf1, length modifiedbuf1 = buf3。我們可以通過(guò)這個(gè)指針描述符間接地修改緩沖區(qū)中的數(shù)據(jù)。 // Constructed from literal descriptorTPtr8 ptr(())。ptr = KPalindrome2。像TBufCn一樣,TBufn也定義了一系列的構(gòu)造方法和賦值操作。如果需要使用動(dòng)態(tài)分配的內(nèi)存,您可以使用基于堆的描述符,這個(gè)我們?cè)诤竺嬉v到。TBuf40 buf1(KPalindrome)。 // Constructed empty, length = 0, maximum length = 40// Illustrate copy and replacebuf4 = buf2。當(dāng)您在編譯的時(shí)候還不能確定緩沖區(qū)長(zhǎng)度的時(shí)候,堆描述符也是很有用的,這時(shí),它的作用相當(dāng)于C語(yǔ)言中的malloc。HBufC定義了靜態(tài)的NewL()方法,用來(lái)在堆上創(chuàng)建一個(gè)緩存區(qū)。TBufC20 stackBuf(KPalindrome)。 // Modification of the heap descriptorptr = stackBuf。 // length = 17_LIT(KPalindrome2, Palindrome)。記住,堆描述符可以按您的要求的尺寸動(dòng)態(tài)分配內(nèi)存,但它不會(huì)自動(dòng)按您的期望更改緩沖區(qū)的大小。因此,為了確保安全,在重新分配內(nèi)存后,應(yīng)該再次調(diào)用Des()來(lái)創(chuàng)建一個(gè)新的TPtr對(duì)象。(Literal Descriptors)下面我們來(lái)看看字面量描述符,它相當(dāng)于C語(yǔ)言中的static char[]。_LIT 宏構(gòu)建了一個(gè)名為KMyLiteralDescriptor的TLitC16對(duì)象,其中保存了字符串的值(在這個(gè)例子中是The quick brown fox jumps over the lazy dog),在二進(jìn)制程序中可以找到這個(gè)值,因?yàn)樗潜粚懙轿募械?。TLitC8也有類似的定義。() const。__TText iBuf[__Align16(S)]。}template TInt Sinline const TDesC16amp。() const{return *operatoramp。您也可以用如下的方法從一個(gè)字面量構(gòu)造一個(gè)指針描述符:TPtrC8 thePtr(KMyLiteralDescriptor)。// 定義一個(gè)包含44字符的字面量_LIT8(KExampleLit8, The quick brown fox jumped over the lazy dog)。為了得到正確的長(zhǎng)度,您可以用公共(public)的成員變量iTypeLength,或者,也可以用更簡(jiǎn)單的方法,使用()操作符來(lái)將字面量轉(zhuǎn)換成一個(gè)描述符,然后用這個(gè)得到的描述符來(lái)得到內(nèi)容的長(zhǎng)度。size = sizeof(KExampleLit16)。這個(gè)代碼的作用相當(dāng)于:_LIT(KLit,Hello world!)。由于沒有長(zhǎng)度值,字面量的內(nèi)存布局不同于描述符,并且當(dāng)代碼運(yùn)行的時(shí)候,_L的第個(gè)實(shí)例都會(huì)產(chǎn)生一個(gè)臨時(shí)的TPtrC,這個(gè)TPtrC的指針指向字面量的第一個(gè)字節(jié)在ROM中的存儲(chǔ)位置。如果您僅將它作為以0結(jié)尾的描述符使用,那么就使用_S宏。同樣的道理,作為函數(shù)的提供者,您可能對(duì)調(diào)用者傳遞進(jìn)來(lái)的參數(shù)類型不感興趣。事實(shí)上,只要標(biāo)準(zhǔn)類型的描述符(我們前面提到的5種描述符類型之一),就可以在它上面調(diào)用適當(dāng)?shù)姆椒?,客戶代碼完全可以忽略描述符的內(nèi)存布局和它在內(nèi)存中的位置。例如,類RFile定義了read()和write()方法IMPORT_C TInt Write(const TDesC8amp。在這兩個(gè)方法中,輸入的描述符被顯式地聲明為8bit的寬度,這樣可以既寫入字符串,也可以寫入二進(jìn)制數(shù)據(jù)。當(dāng)文件中的數(shù)據(jù)不夠描述符的最大長(zhǎng)度時(shí),文件服務(wù)器會(huì)把所有可得的數(shù)據(jù)寫入描述符。當(dāng)然,您也可能不希望在描述符數(shù)據(jù)區(qū)過(guò)短的情況下,描述符的方法會(huì)發(fā)生系統(tǒng)異常。 aDes){HBufC* line = DoGetLineL(aLineNumber)。}// Leave amp。}}另一個(gè)方案是,在函數(shù)中分配堆緩沖區(qū),把它返還給調(diào)用者,由調(diào)用者負(fù)責(zé)銷毀它。 代碼如下所示:216。 MaxLength() 可修改的描述符TDes實(shí)現(xiàn)的這個(gè)方法返回描述符的最大長(zhǎng)度。216。216。aDes)。 首先,我們將創(chuàng)建和使用堆描述符HBufC。TPtr ptr(iHeapBufferDes())。}Another mon way to introduce plexity occurs in the oppositedirection, that is, the generation of TDesCamp。 CSampleClass::MoreAccidentalComplexity(){return (iHeapBufferDes())。TPtr p = bufDes()。堆描述符的最大長(zhǎng)度有可能并不是您所期望的值(在這個(gè)例子中為9)。void TestPointer(){ // Create a buffer with length KBufferLength = 9 bytesHBufC8* myBuffer = HBufC8::NewMaxL(KBufferLength)。 //得到一個(gè)比KBufferLength稍大數(shù),并不固定(KBufferLength)。//確保已經(jīng)調(diào)用了SetLength()或SetMax()方法。TPtr8 ptr(bufDes())。 // = 256 (decimal)typedef TBufKMaxFileName TFileName。如果,您不需要使用完整的路徑,你也可以用HBufC來(lái)存放文件名,盡量少用資源總是好的。4有用的輔助類在討論了這些普遍的問(wèn)題之后,我們?cè)谶@一章的結(jié)尾來(lái)看看兩個(gè)常用的輔助類。打包類(package class)能很方便地將扁平的(flat)數(shù)據(jù)對(duì)象存儲(chǔ)到描述符中,這在跨線程或跨進(jìn)程的數(shù)據(jù)共享的時(shí)候很有用。 void ConstantSampleFunction() const。TPckgTSample packagePtr(theSample)。代碼如下:packagePtr().SampleFunction()。這個(gè)TPckgBuf對(duì)象所擁有的拷貝可以被修改。下面的圖示表明了它們的內(nèi)存布局:23 / 23