Symbian系统开发教程2_第1页
Symbian系统开发教程2_第2页
Symbian系统开发教程2_第3页
Symbian系统开发教程2_第4页
Symbian系统开发教程2_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、.:.;:数据类型与语法谢兴 HYPERLINK mailto:enigma19971hotmail enigma19971hotmail 转载需注明出处Symbian系统曾经提供了一套曾经定义好的内置的数据类型。为了保证他的代码是编译器无关的,该当运用下面symbian系统提供的数据类型,而不要运用原生数据类型native types,这里指规范C中的int ,char等。根本类型TIntX 和 TUintX (其中X = 8, 16 和 32) 分别用来表示 8位, 16位 和 32位的有符号和无符号的整数。 普通情况下,运用TInt 和TUint就可以了,除非是在思索代码优化或兼容性的时

2、候,才会用到TInt8,TInt16这样的类型。TInt 或 TUint 类型分别对应有符号和无符号的整数。TInt64. 在版本8.0之前,Symbian系统中不支持64位的算术运算,而是用两个32位的值来实现64位的整数,在8.0版本之后,TInt64和TUInt64才被定义为long long类型,真正运用64位的内置数据类型。TReal32 和 TReal64 (TReal相当于TReal64) 这两个数据类型相当于单精度和双精度的浮点数,由于浮点数的运算要比整数慢,所以普通应尽量防止运用浮点数的运算。TTextX (其中X = 8 或 16) 分别对应窄或宽的字符注:所谓窄字符通常A

3、SCII码字符,而宽字符是指unicode字符集的字符 TAny*TAny* 意为指向恣意内容的指针,在这种意义上讲,TAny相当于void, TAny* 相当于TAny*。但是,在某些场所下,void标示空,如:void hello(void);这时,不要将它改写为: TAny hello(TAny);TBool 标示布尔类型。Symbian系统提供了两个常量:ETrue (=1) 和 EFalse (=0),分别表示真和假。留意:在Symbian系统中,TBool被定义为int, 而ETrue和EFalse被定义为enum,所以,假设一个函数的前往值为TBool,不要用如下的代码来比较函数

4、的前往值:TBool isLargerTInt a, TInt breturn (ab)?ETrue:EFalse; if(isLarger(4,3)=ETrue). /错误,编译不过。if(isLarger(4,3). /正确2类和对象2.1 Symbian系统中的命名习惯:在Symbian系统中编写代码时,该当遵守种样几个规那么:成员变量的命名以小写字母i开头,方法的参数以小写字母a开头,例如:class Pernonpublic:TInt iAge;void SetAge(TInt aAge)iAge = aAge;在symbian系统中存在几种不同类型的类class,不同类型的类,其特

5、性也各不一样。有的在堆heap上创建,有的在栈stack上创建,特别的是,类的实例instance的去除方式也不尽一样下面,为了方便我们把类的类别称为型别。型别class type可以表达这些不同的特点。每个型别都有一套定义好的关于如何创建和去除实例的规那么。为了容易区分型别,Symbian系统运用了一个简单的命名规那么:类名以大写字母开头T,C,R 或M。作为类的设计者,他先要思索这个类的行为,看它究竟与哪种型别匹配,一旦确定了它的类型,然后他就可以专注于该类的功能。同样,对一个类的运用者来讲,假设他不熟习这个类, 但类的命名规那么可以协助 他弄清他的意图-如何用平安的方式初始化、运用和销毁

6、一个类的对象object。下面,我主要讨论不同型别的主要特性。T 类T类的行为类似于C+中的内置类型,因此,它们以T作前缀(T代表Type)。象内置类型一样,它们没有析构方法destructor,这导致的结果是:T类不能包含具有析构方法的成员变量。所以,普通情况下,T类的成员变量只能是内置类型的数据或者是其它的T类的对象。在某些的情况下T类也可以包含其它对象的指针或援用,不过,这时它们之前是“运用关系,而不是“拥有关系也就是说,这个T类对象并不担任对成员的创建和销毁的任务。不能拥有外部数据的缘由是由于T类没有析构方法。正是由于没有析构方法,T类的对象可以在栈上创建,当程序流程退出函数或产生le

7、ave一种代码异常的时候,系统自动去除它。即使T类有一个析构方法,在发生异常在Symbian系统中,异常被称为leave时Symbian 系统也不会调用它,由于leave没有模拟规范C+的抛出异常的做法。T类的对象也可以在堆上创建。但是,该当在调用有能够发生异常的代码之前,将这个对象放入到去除栈cleanupStack,在发生异常的时候,去除栈cleanupStack会释放这个对象。C 类这种类都是从CBase派生来的直接或间接。/.h fileclass CStudent:public CBase public:CStudent()RDebug:Print(_L(i am a student

8、);CStudent()RDebug:Print(_L(please, dont kill me!);void SampleFunction();private:TInt iCode;TInt iScore;CBase有两个特点:首先,它有一个虚的析构方法,这样,可以经过CBase指针来删除它的子类。代码如下所示:CBase *pStu = new CStudent();delete pStu;结果: i am a student please, dont kill me! 其次,CBase类和它的子类,重载了new操作符,这使得当它在堆上创建的时候,自动初始化为0,也就是说,当它一开场被创建

9、出来的时候,一切的成员变量都被初始化为0,所以您不用在构造方法中去做这件事情。但是,在栈上创建对象时,情况并非这样, 由于这时没有用到new操作。这将潜在地导致堆上创建的对象和栈上创建的对象的行为不一致。因此,C类的对象一定要在堆上创建。很明显,当一个堆上的C类对象不再被需求时,我们需求耗费它。 一个C类的对象能够以两种方式存在:其它类的指针成员变量或是一个部分的针指变量。在前一种情况下,我们可以在类的析构方法中调用delete来删除它;后一种情况要复杂一些,在调用任何有潜在的异常leave的代码之前,要把这个指针放到去除栈cleanup stack中,否那么有能够发生内存泄露。CBase 类

10、声明了私有的拷贝构造方法和赋值操作=。这是一个很好的战略,它可以用来防止客户代码不小心地运用了浅拷贝或赋值的方法。由于基类的拷贝构造和赋值是私有的,所以,假设您希望您的类可以可以运用拷贝构造方法,您必需显式地声明和定义拷贝构造方法和赋值操作。但是,思索到C类的特性,深拷贝能够呵斥发生异常leave的隐患,而您绝对不能让类的构造方法或析构方法发生异常我们在本教程的后面解释缘由。所以,假设您确实需求一个拷贝的方法,那么您可以为类添加一个的能够会发生异常的方法来完成同样的义务,例如:CloneL()或CopyL()。假设您提供的这个类是从CBase派生的,您就不用为了防止客户代码运用有潜在平安问题的

11、“浅拷贝,而在代码中将这些方法声明为私有的。R 类前缀“R 在这里代表资源Resource, 通常是外部资源,例如:文件的句柄handle。 和C类不同,Symbian系统中不存在一个对应的RBase类,所以一个R类该当有一个构造方法来将它的资源句柄置为0,阐明还没有资源和这个新建的对象关联在一同。但是,不要在构造方法中初始化资源句柄,由于这样有能够使构造方法产生异常。R类中经常有类如Open(), Create() 或 Initialize()这样的方法,它们用来分配资源,设置句柄成员变量的值,并前往错误代码或是产生异常。 R类通常也有对应的Close或Reset()类,用来释放资源,重置句

12、柄的值-阐明没有资源和该对象关联。运用R类时,一个常见的错误是忘记调用它的Close()方法当然,该方法也可以是其它名字,但它经常被命名为Close或是有一个析构方法释放资源,这会引起资源的泄露。R类通常都很小,除了资源句柄没有其它的成员变量。由于不需求。它通常也没有析构方法,资源的释放都是在Close()方法中进展的。大多数情况下,R类都是作为类的成员变量或部分变量存在的。只需少数情况下,在堆上创建。您必需确保,当程序发后异常的时候,资源能被正确地释放-通常是运用资源栈。假设一个R类是一个堆上的自动变量相对于成员变量,您一但要保证资源被释放,而且,变量本身也要被释放。typically by

13、 using two push calls: CleanupClosePushL(), or asimilar function,to ensure that the resource is cleaned up, and a standard CleanupStack:PushL(TAny*) which simply calls User:Free() on the heap cell.R类的成员变量通常都很简单,所以普通不需求深拷贝bitwise copy。R类的拷贝能够会引起混乱想象一下:假设两个对象同时在一个资源句柄上调用Close()方法,或两个对象都没有释放资源,会发生什么情况?

14、假设,您想阻止任何对R类的拷贝,您该当声明但不定义一个私有的构造方法和赋值操作。M 类当提到多承继的时候,它意味着从一个主要的类派生,同时也混杂基它类的功能。前缀M是单词Mixin的首字母。Symbian系统不赞成多承继的做法,由于这个引入额外的复杂性,M类是一个笼统类,它的作用相当于java中的接口interface。在Symbian系统中,M 类常被用来定义回调接口或者是察看者observer类。M类也可以被其它类承继。下面我们给出两个例子。class MAnimalpublic:virtual void EatL() =0;class MDomesticAnimal : public M

15、Animalpublic:virtual void NameL() =0;class CCat : public CBase, public MDomesticAnimalpublic:virtual void EatL(); / 从MAnimal, 经过MDomesticAnimal承继virtual void NameL(); / 从 MDomesticAnimal承继/ Other functions omitted for clarity;上面的例子演示了一个从CBase类和一个M类派生的详细类。而类MDomesticAnimal又是从MAnimal派生的。象接口一样,由于不能被实例化

16、,M类只能有虚virtual函数,不能有成员变量和构造方法。但它可以有析构方法, 条件是,实现它的详细类必需是从CBase派生的。在定义完类以后,然后可以用运用它。代码如下:CCat *cat1 = new CCat;delete cat1; /正确然下面的代码却是错误的。MAnimal *cat2 = new CCat;delete cat1; /错误当用M类的指针援用一个对象的时候,假设用delete删除这个指针,那么这个M类必需提供一个虚拟的析构方法,否那么会出现系统异常panic code 42。将MAnimal的代码改写,那么上面代码没有问题。class MAnimalpublic:

17、virtual void EatL() =0;virtual MAnimal(); /添加一个虚的析构方法。;3描画符descriptor在Symbian 系统中,字符串被称为“描画符descriptor,由于它们是自我描画的。在描画符中保管了它所表示的字符串的长度和它的底层的内存规划的信息。描画符比规范C中的字符数组和字符指针要复杂,您能够需求多花些时间来学习和掌握它的用法。关键是,它们的特殊设计使得它们在少量内存的设备上非常有效率,仅用非常少的内存就可以保管本人的长度和内存规划的信息。如今,让我们来深化了解描画符的设计思想。在Symbian系统中,描画符是相当让人迷惑的,由于它的种类繁多。

18、不同种类的描画符具有不同的特性和用法,但又经常能相互转换。它们不同于规范C+中的string,java言语中的string类或MFC中的CString,由于程序员必需本人管理底层的内存分配和去除任务。它们具有防治内存溢出的机制,并且不依赖NULL终结符号来决议字符串的长度,从这方而来讲,它也不同于C言语中的字符串。如今我们来讨论:什么是描画符?它们是如何任务的?在讨论这些不同的描画符之前,先让我们需求弄清楚一个根本的概念:什么是字符串数据的“宽度?这个长度指的是单个字符是8bit的,还是16bit的宽度。在早期的版本中,字符的宽度都是8bit的,后来为了支持Unicode字符集,从第5版起,S

19、ymbian系统将16bit 的字符作为标 准。Symbian系统如今支持这两种字符长度的描画符,除了Copy()和Size()两个方法以外,这两种宽度的描画符的行为是完全一致的,这两个方法的运用,我们后面再引见。另外,有一套中立的描画符类型,它们既可以被定义为窄的描画符类型,也可以被定义为宽的描画符类型,这要取决于编译时的宽度。您可以从它的名字上很容易看出这个类型所表示的宽度。假设,它以8结尾例如:TPtr8,就意味着它表示是的8bit的窄字符,而以16结尾的描画符类例如:TPtr16那么操作16bit的宽字符。 对中立neutral的类型来讲,没有数字结尾例如:TPtr,在Symbian系

20、统第5版以后,默许的情况下,它们表示宽度为16bit的字符串。它们之间的关系比较类似于TInt,TInt16或TInt32 之间的关系,这一点该当是比较易于了解的。普通情况下,您没有必要指明是字符串的宽度,用中立的类型就可以了,这样使他的代码易于在宽字符版本和窄字符版本之间转换有过编程阅历的朋友应该有这样的印象,我们平常写代码,大多情况下,仅仅运用UINT类型,而较少思索运用UINT16,UINT32类型。另外一个问题是:描画符和字面量literal的区别。所谓字面量是指在编码的时候就曾经确定的量,例如,规范C中的 char* p = Hello world;其中的Hello world就是字

21、面量。在Symbian系统中,对它们的处置是很不一样的,这点我们在后面再引见。有了这样的一些认识, 如今我们可以来看看有哪些描画符类型。在Symbian系统中描画符类型有两大种类:不可修正non-modifiable的描画符和可修正(modifiable)的描画符。3.1不可修正non-modifiable的描画符 在Symbian系统中,一切的描画符都承继自TDesC,在前面我们曾经讨论了类名前缀T所代表的意义,在这里,我们更关怀类名的后缀C所代表的意义,这个C是单词Constant的首字符,表示这个类是不可更改的。这个类提供了一些用来前往字符串的长度和操作数据的方法。Length方法前往了

22、描画符的长度,由于,每个描画符对象在内存中的规划都是同样的,用4个字节来表示它所包含的数据的长度实践上,只用了32个bit中的28个bit,剩余的4bit留作它用,所以描画符能表示的最大的长度为228 字节,256 MB,不过这曾经足够了。所以,Length方法没有被它的子类重写,它对一切子类都有效。但是,根据实现子类的方法的不同,子类访问数据的方式也不一样,Symbian系统不要求它的子类经过虚函数的方式来实现本人的访问数据的方法。 不用虚函数重写的缘由是由于,虚函数会给每个被派生的描画符对象添加4节字的额外负担,c+用这4个字节来存放指向虚函数表的指针。我们前面说过,在设计描画符的时候要让

23、它尽能够高效,额外的字节开销被以为是不理想的。存放长度的4个字节中,28bit用来表示长度,剩下的4bit用来表示描画符的类型。目前,symbian系统中有5种派生的描画符类型,4bit限制了描画符的种类最多只能有16种,但这曾经足够了。子类可以经过调用基类TDesC的Ptr方法来访问描画符的数据,Ptr()方法检查这4个bit,确定描画符的类型并前往它的数据在内存中的地址。当然,这要求TDesC基类清楚它的子类的内存规划,并在Ptr方法中运用硬编码的方法。后面,为了表述上的方便,我们也把这种不可修正的描画符也称为常量描画符constant descriptor总结:不可修正的描画符类TDes

24、C是一切的非字面量描画符的基类,它提供了确定描画符长度和访问数据的方法,另外,它实现了一切的您想用来处置常量字符串的操作。3.2可修正modifiable的描画符一切的可修正的描画符都从TDes基类派生,而TDes本身又是从TDesC派生的。TDes有一个额外的成员变量用来存放为该描画符分配数据的最大长度。MaxLength()方法前往了这个最大的长度。像TDesC中的Length方法一样,MaxLength()方法也不被TDes的子类承继。TDes类提供了一系列的方法, 用来对可修正字符串数据的操作,包括对字符串的附加、填充和格式化操作。一切的这些方法都被派生类承继,派生类只实现一些特定的构

25、造方法和复制赋值的方法。这些方法都不担任分配内存,假设它们超越了描画符的数据长度,例如,用Append方法在某个字符串后面附加另一个字符串时,在调用该方法之前,您必需确保有足够的内存空间。当然,只需不超越描画符的最大存储容量,描画符的长度可以自在地伸缩。当描画符长度比最大长度短的时候,描画符的后面部分是多余未用的。这些方法运用了断言assertion来确保描画符的最大长度不会被超出。假设发生内存溢出,将会产生一个panic关于panic,我们将在后面的章节引见,这样可以方便您检查和修正程序的错误。现实上,不能够使描画符溢出,这一点保证了您代码的强健性,而且不易产生难以跟踪的内存圈套。但需求留意

26、的是,由于基类的构造方法是proteced类型的,所以您无法直接实例化一个TDesC或TDes类的实例。如今我们来看看描画符的派生类,您可以实例化和运用派生类的对象。正如前面所说,这个地方是比较让人迷惑的,由于描画符存在大量的派生类。 前面,我们曾经解释过为什么每个类会有三个不同的版本,例如:TDes8, TDes16 和 TDes,分别对应窄字符,宽字符和中立的类。如今,让我们看看有哪些主要的描画符类型,在深化讨论每种类型的细节之前,我们先调查一下它们在普通情况下的内存规划。描画符有两种根本的内存规划:指针描画符和缓存区描画符。不同之处在于,指针描画符持有一个指向字符串的指针,而这个字符串存

27、储在内存中的基它位置。与指针描画符不同,缓存区描画符本身持有字符数据,也就是说字符数据本身构成了描画符的一部分。总结:TDes 是一切的可修正的描画符的基类, 并且它本人也是从TDesC派生的。它有一个能前往最大的内存容量的方法和一系列的用来修正字符串数据的方法。3.3 指针描画符pointer descriptor指针描画符可分为两种:TPtrC 和TPtr我们前面说过,每种类型的描画符,按照字符宽度,都可以分为三个版本,例如:窄字符版本TPtrC8,宽字窄版本TPtrC16和中立的版本TPtrC,所以严厉来讲,有六种指针描画符。指针描画符所持有的字符串是跟描画符本身分开来存放的,它可以被存

28、储在ROM中,堆中或栈中。由于保管数据的内存既不为描画符所拥有,也不经过它来管理。所以,假设要该描画符是在堆上分配的,那么应经过堆描画符HBufC,下面将要讲解来操作内存的分配和销毁;假设指针描画符所指向的字符串是在栈上分配的,那这个内存必需是曾经在栈上分配好的。通常情况下,指针描画符是基于栈的,但有时候,它们也可以在堆上运用,例如:作为一个CBase派生类的成员变量的时候。在不可修正的描画符TPtrC中,指向数据的指针存放在长度的后面,因此,指针描画符的总长度为2个字word;在可修正的指针描画符中,它存放在最大长度的后面,因此,总长度为3个字。以下图比较了TPtr和TPtrC内存规划.iL

29、ength(12)iMaxLengthiPtrHello world!iLength(12)iPtrTPtrCTPtr TPtrCTPtrC相当于C言语中的const char*。被它指向的数据可以被访问但不能被修正:也就是说,描画符中的数据是常量。一切的从基类TDesC中承继的操作都是可访问的。TPtrC定义了一系列的构造方法,使得它能从其它的描画符、指向内存的指针或以0结尾的C言语字符串构造。/ 字面量描画符将在后面引见_LIT(KLiteralDes, Sixty zippers were quickly picked from the wovenjute bag);TPtrC pang

30、ramPtr(KLiteralDes); / 从字面量描画符构造TPtrC copyPtr(pangramPtr); / 从其它的描画符构造TBufC constBuffer(KLiteralDes); / 常量缓存区描画符,后面引见TPtrC ptr(constBuffer); / Constructed from a TBufC/ TText8 is a single (8-bit) character, equivalent to unsigned charconst TText8* cString = (TText8*)Waltz, bad nymph, for quick jigsv

31、ex;/ 从以0结尾的字符串构造TPtrC8 anotherPtr(cString);TUint8* memoryLocation; / Pointer into memory initialized elsewhereTInt length; / Length of memory to be represented.TPtrC8 memPtr(memoryLocation,length); / 从一个指针构造。这个指针本身可以改动成指向其他的字符串数据(经过Set方法)。假设您想指明,不能改动您的TPtrC所指向的数据,那么您可以将TPtrC声明为const,这样,当您试图用Set方法更改T

32、PtrC所指向的数据时,编译器会产生警告。/ 字面量描画符_LIT(KLiteralDes1, Sixty zippers were quickly picked from the woven jutebag);_LIT(KLiteralDes2, Waltz, bad nymph, for quick jigs vex);TPtrC alpha(KLiteralDes1);TPtrC beta(KLiteralDes2);alpha.Set(KLiteralDes2); / alpha points to the data in KLiteralDes2beta.Set(KLiteralDe

33、s1); / beta points to the data in KLiteralDes1const TPtrC gamma(beta); / Points to the data in beta, KLiteralDes1gamma.Set(alpha); / Generates a warning, but points to alpha这里该当加一些示范代码TPtrTPtr 是可修正的指针描画符,它可用来访问和修正字符串或二进制数据。TDesC 和TDes所提供的一切的操作都适用于TPtr。这个类定义了一些构造方法,使得它能从指向内存的指针构造,并设置适当的长度值和最大长度值。编译器也

34、会产生隐式的构造方法和拷贝构造方法,由于它们没有被声明为维护的或私有的。一个TPtr对象可以从其它的可修正描画符构造,例如:经过在不可修正的描画符上调用Des方法,这个方法前往一个如下所示的TPtr对象:_LIT(KLiteralDes1, Jackdaws love my big sphinx of quartz);TBufC buf(KLiteralDes1); / TBufC are described laterTPtr ptr(buf.Des(); / Copy construction; can modify the data in bufTInt length = ptr.Len

35、gth(); / Length = 37TInt maxLength = ptr.MaxLength(); / Maximum length = 60, as for bufTUint8* memoryLocation; / Valid pointer into memory.TInt len = 12; / Length of data to be representedTInt maxLen = 32; / Maximum length to be represented/ Construct a pointer descriptor from a pointer into memoryT

36、Ptr8 memPtr(memoryLocation, maxLen); / length = 0, max length = 32TPtr8 memPtr2(memoryLocation, len, maxLen); / length = 12, max = 32另外,TPtr提供了赋值运算符=(),用来拷贝数据到指针所指向的内存数据源可以是可修正、不可修正的指针描画符,或以0结尾的字符串。假设要拷贝的数据的长度超越了描画符的最大长度,会引发一个系统异常。像TPtrC一样,TPtr也定义了一个Set方法,用来改动描画符所指向的数据。_LIT(KLiteralDes1, Jackdaws lo

37、ve my big sphinx of quartz);TBufC buf(KLiteralDes1); / TBufC are described laterTPtr ptr(buf.Des(); / Points to the contents of bufTUint16* memoryLocation; / Valid pointer into memory.TInt maxLen = 40; / Maximum length to be representedTPtr memPtr(memoryLocation, maxLen); / length = 12, max length =

38、 40/ Copy and replacememPtr = ptr; / memPtr data is KLiteralDes1 (37 bytes), maxLength = 40_LIT(KLiteralDes2, The quick brown fox jumps over the lazy dog);TBufC buf2(KLiteralDes2); / TBufC are described laterTPtr ptr2(buf2.Des(); / Points to the data in buf/ Replace what ptr points toptr.Set(ptr2);

39、/ ptr points to contents of buf2, max length = 100memPtr = ptr2; / Attempt to update memPtr which panics because the/ contents of ptr2 (43 bytes) exceeds max length of memPtr (40 bytes)您一定不要混淆了Set方法和=()赋值操作。前者将描画符的指针重置,使它指向新的数据区域,而后者将数据拷贝到描画符中,普通来说,这会更改描画符的长度,但不会更改它的最大长度值。3.5 基于栈stack-based的缓冲区描画符基于

40、缓冲区的描画符也可以分为可修正的TBuf和不可修正TBufC的两种类型。对这种描画符来讲,字符串数据本身就是描画符的一部分。以下图给出了描画符的内存规划:iLength 12iMaxLengthHello World!TBufiLength 12Hello World!TBufC这两种描画符通常用来存储定长的或相对较小的字符串,常用来存放长度小于256个字符的文件名。类似于C言语中的char,但是,它们具有检查内存溢出的功能。TBufCTBufC是不可修正的缓冲区类型,它主要用来存放字符串常量或是二进制数据。该类从TBufCBase类派生,尖括号内的数字表示分配给该描画符的数据区的大小。它定义

41、了一些构造方法,允许从其它的描画符或以0结尾的字符串构造。也允许创建一个空的描画符,然后再填充。由于该描画符的数据是不可修正的,它的整个内容可以被置换经过该类的所定义的赋值操作,用来置换的数据可以是其它的不可修正的描画符或是0结尾的字符串,但是,无论是何种情况,新数据的长度都不能超越长度n也就是创建该类的时候指定的模板参数。_LIT(KPalindrome, Satan, oscillate my metallic sonatas);TBufC buf1(KPalindrome); / Constructed from literal descriptorTBufC buf2(buf1); /

42、 Constructed from buf1/ Constructed from a NULL-terminated C stringTBufC buf3(TText*)Never odd or even);TBufC buf4; / Constructed empty, length = 0/ Copy and replacebuf4 = buf1; / buf4 contains data copied from buf1, length modifiedbuf1 = buf3; / buf1 contains data copied from buf3, length modifiedb

43、uf3 = buf2; / Panic! Max length of buf3 is insufficient for buf2 data该描画符中的数据可以被整体置换,但不能被直接修正,但有时候我们确实需求修正缓存区中的数据,该怎样办呢?系统提供了另一种途径来修正数据。该类定义了Des方法,它为缓存区中的数据前往一个可修正的指针描画符TPtr。我们可以经过这个指针描画符间接地修正缓冲区中的数据。当数据经过指针描画符被修正以后,指针描画符和缓冲区描画符中的iLength的值会跟着改动,但要记住,缓存区描画符的长度值只能够减小,而是不能够增大的,由于,描画符类是不提供内存管理管理功能的。_LIT

44、8(KPalindrome, Satan, oscillate my metallic sonatas);TBufC8 buf(KPalindrome); / Constructed from literal descriptorTPtr8 ptr(buf.Des(); / data is the string in buf, max length = 40/ Illustrates the use of ptr to copy and replace contents of bufptr = (TText8*)Do Geese see God?;ASSERT(ptr.Length()=buf

45、.Length();_LIT8(KPalindrome2, Are we not drawn onward, we few, drawn onward tonew era?);ptr = KPalindrome2; / Panic! KPalindrome2 exceeds max length of ptr(=40)TBuf这也是一个模板类,它是一个可修正的缓冲区描画符类,后面的表示缓冲区大小。TBuf从TBufBase类派生,而TBufBase是从TDes派生的,因此,它承继了TDes和TDesC类一切的方法。像TBufC一样,TBuf也定义了一系列的构造方法和赋值操作。对一切的描画符类型

46、来讲,内存管理是您的责任,虽然这个缓冲区中的数据是可修正的,但它的长度不能超越在构造方法中所给定的最大值n。假设缓冲区的内容需求扩展,那么您必需决议是在编译的时候就给定一个足够大的值,或是在运转的时候动态分配内存。但无论哪种情况,都要确保数据长度不要超越缓存区的最大长度。假设需求运用动态分配的内存,您可以运用基于堆的描画符,这个我们在后面要讲到。要是您觉得管理内存分配的义务太过繁重,您也可以选择运用动态数组。不过,您该当记住,运用动态数组的额外开销是很高的。_LIT(KPalindrome, Satan, oscillate my metallic sonatas);TBuf buf1(KPa

47、lindrome); / Constructed from literal descriptorTBuf buf2(buf1); / Constructed from constant buffer descriptorTBuf8 buf3(TText8*)Do Geese see God?); / from C stringTBuf buf4; / Constructed empty, length = 0, maximum length = 40/ Illustrate copy and replacebuf4 = buf2; / buf2 copied into buf4, updati

48、ng length and max lengthbuf3 = (TText8*)Murder for a jar of red rum; / updated from C string3.6 基于堆的Heap-Based缓冲区描画符当您要运用非常长的字符串时,有另外一种选择:基于堆的描画符。它能拥有比它的创建者更长的生存期。当您在编译的时候还不能确定缓冲区长度的时候,堆描画符也是很有用的,这时,它的作用相当于C言语中的malloc。HBufC也许您曾经发现,HBufC的类名以“H开头,这不符合Symbian系统中惯用的命名习惯。这确实是一个特例,“H表示这个类普通是在堆Heap上分配的。HBu

49、fC定义了静态的NewL方法,用来在堆上创建一个缓存区。正如您所见到,HBufC中的字母“C表示这个表述符是不可修正的。对该类的操作几乎和TBufC一样:该类提供了一套赋值操作,允许整个缓冲区中的内容被交换掉;同样,新内容的长度不能超越缓存区的大小,否那么会引起系统异常;经过调用Des()方法,可以前往一个可修正的指针描画符TPtr,可以经过这个指针描画符来更改缓冲区中的内容。_LIT(KPalindrome, Do Geese see God?);TBufC stackBuf(KPalindrome);/ Allocates an empty heap descriptor of max l

50、ength 20HBufC* heapBuf = HBufC:NewLC(20);TInt length = heapBuf-Length();/ Current length = 0TPtr ptr(heapBuf-Des(); / Modification of the heap descriptorptr = stackBuf; / Copies stackBuf contents into heapBuflength = heapBuf-Length(); / length = 17HBufC* heapBuf2 = stackBuf.AllocLC(); / From stack b

51、ufferlength = heapBuf2-Length(); / length = 17_LIT(KPalindrome2, Palindrome);*heapBuf2 = KPalindrome2; / Copy and replace data in heapBuf2length = heapBuf2-Length(); / length = 10CleanupStack:PopAndDestroy(2, heapBuf);记住,堆描画符可以按您的要求的尺寸动态分配内存,但它不会自动按您的期望更改缓冲区的大小。在修正缓存区 的内容之前,您要确保缓存区的内存是足够的。为了帮您简化这些操作

52、,HBufC提供的一套ReAllocL()方法,它可以用来扩展堆的缓存区这个操作有能够会使缓冲区从一个内存区域搬到另一个区域。If the HBufC* is stored on the cleanup stack, moving the pointer as a result of memory reallocation can cause signi.cant problems either in the event of a leave or if the cleanup stacks PopAndDestroy() function is used to destroythe memo

53、ry.假设您在HBufC上调用Des()方法来获取了TPtr, 在经过重新分配内存后,TPtr中的成员变量iPtr有能够变成无效的。因此,为了确保平安,在重新分配内存后,应该再次调用Des来创建一个新的TPtr对象。注:出于性能上的思索,Symbian系统并没有提供可修正的堆描画符HBuf。总结:Symbian系统中总共有5种类型的描画符,TPtrC,PTtr,TBufC,TBuf和HBufC。下面的图示阐明了它们的承继关系。3.7字面量描画符Literal Descriptors下面我们来看看字面量描画符,它相当于C言语中的static char。字面量描画符是经过一系列的宏来创建的,这些宏

54、可在头文件e32def.H中找到#define _L8(a) (TPtrC8(const TText8 *)(a)#define _S8(a) (const TText8 *)a)#define _LIT8(name,s) const static TLitC8name =sizeof(s)-1,s#define _L16(a) (TPtrC16(const TText16 *)L # a)#define _S16(a) (const TText16 *)L # a)#define _LIT16(name,s) const static TLitC16name =sizeof(L#s)/2-1

55、,L#s首先,我们来看_LIT,这是最有效率也是被运用得最多的一个。这个宏的用法如下:_LIT(KMyLiteralDescriptor, The quick brown fox jumps over the lazy dog);后面KMyLiteralDescriptor就可以作为一个常量来运用,例如可以将它写到文件或显示给用户。_LIT 宏构建了一个名为KMyLiteralDescriptor的TLitC16对象,其中保管了字符串的值在这个例子中是The quick brown fox jumps over the lazy dog,在二进制程序中可以找到这个值,由于它是被写到文件中的。如

56、您所料,_LIT8和_LIT16的用法类似。由于描画符的宽度为16bit,所以,在将C字节类型的字符串转换为描画符能用的数据时,宏将字符串的长度除以2。作为参考,下面给出类TLitC16的定义,其中_TText被定义为宽的,16bit的字符。TLitC8也有类似的定义。template class TLitC16public:inline const TDesC16* operator&() const;inline operator const TDesC16&() const;inline const TDesC16& operator()() const;. / Omitted for

57、claritypublic:TUint iTypeLength;_TText iBuf_Align16(S);template inline const TDesC16* TLitC16:operator&() constreturn REINTERPRET_CAST(const TDesC16*,this);template inline const TDesC16& TLitC16:operator()() constreturn *operator&();template inline TLitC16:operator const TDesC16&() constreturn *oper

58、ator&();从上面的定义中可以看到, TLitC16 (和TLitC8) 并不从TDesC8 或 TDesC16派生,但是它们与TBufC8 或TBufC16具有一样的内存规划。这就使得TLitC16 (和TLitC8)可以用在任何可以运用TDesC的地方。您也可以用如下的方法从一个字面量构造一个指针描画符:TPtrC8 thePtr(KMyLiteralDescriptor);从字面量构造缓冲区描画符需求一点小技巧。假设您用size去获得_LIT常量,它会前往相应的TLitC对象的尺寸大小,这个尺寸相当于描画符内容的尺寸加上额外的8个byte用来存放长度值的4字节和表示终了符的NULL。

59、假设您想用它来构造基于堆的描画符,必需求将这额外的8个字节思索进去。/ 定义一个包含44字符的字面量_LIT8(KExampleLit8, The quick brown fox jumped over the lazy dog);TInt size = sizeof(KExampleLit8); / 52 bytes (contents + 8 bytes)TBufC8 theStackBuffer(KExampleLit8);对基于堆的描画符,您可以用描画符实践内容的长度来分配缓冲区,然后将内容拷贝到描画符中。为了得到正确的长度,您可以用公共public的成员变量iTypeLength,或

60、者,也可以用更简单的方法,运用操作符来将字面量转换成一个描画符,然后用这个得到的描画符来得到内容的长度。但最简单的方法是,运用操作符将对象转换成描画符后,直接调用TDes:AllocL()方法,前往一个HBufC*,代码如下:TInt descriptorLength = KExampleLit8.iTypeLength; / 44 bytes/ Form a stack buffer descriptor around the literal/ Create a heap buffer copying the contents of the literalHBufC8* theHeapBuf

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论