Symbian系统开发教程2

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第二章:数据类型与语法作者:谢兴enigma19971@hotmail.com转载需注明出处Symbian系统已经提供了一套已经定义好的内置的数据类型。为了保证你的代码是编译器无关的,应当使用下面symbian系统提供的数据类型,而不要使用原生数据类型(nativetypes,这里指标准C中的int,char等)。1.基本类型TIntX和TUintX(其中X=8,16和32)分别用来表示8位,16位和32位的有符号和无符号的整数。一般情况下,使用TInt和TUint就可以了,除非是在考虑代码优化或兼容性的时候,才会用到TInt8,TInt16这样的类型。TInt或TUint类型分别对应有符号和无符号的整数。TInt64.在版本8.0之前,Symbian系统中不支持64位的算术运算,而是用两个32位的值来实现64位的整数,在8.0版本之后,TInt64和TUInt64才被定义为longlong类型,真正使用64位的内置数据类型。TReal32和TReal64(TReal相当于TReal64)这两个数据类型相当于单精度和双精度的浮点数,由于浮点数的运算要比整数慢,所以一般应尽量避免使用浮点数的运算。TTextX(其中X=8或16)分别对应窄或宽的字符(注:所谓窄字符通常ASCII码字符,而宽字符是指unicode字符集的字符)TAny*TAny*意为指向任意内容的指针,在这种意义上讲,TAny相当于void,TAny*相当于TAny*。但是,在某些场合下,void标示‘空’,如:voidhello(void);这时,不要将它改写为:TAnyhello(TAny);TBool标示布尔类型。Symbian系统提供了两个常量:ETrue(=1)和EFalse(=0),分别表示真和假。注意:在Symbian系统中,TBool被定义为int,而ETrue和EFalse被定义为enum,所以,如果一个函数的返回值为TBool,不要用如下的代码来比较函数的返回值:TBoolisLarger(TInta,TIntb){return(ab)?ETrue:EFalse;}if(isLarger(4,3)==ETrue){...}//错误,编译不过。if(isLarger(4,3)){...}//正确2类和对象2.1Symbian系统中的命名习惯:在Symbian系统中编写代码时,应当遵守种样几个规则:成员变量的命名以小写字母i开头,方法的参数以小写字母a开头,例如:classPernon{public:TIntiAge;voidSetAge(TIntaAge){iAge=aAge};}在symbian系统中存在几种不同类型的类(class),不同类型的类,其特性也各不相同。有的在堆(heap)上创建,有的在栈(stack)上创建,特别的是,类的实例(instance)的清除方式也不尽相同(下面,为了方便我们把类的类别称为型别)。型别(classtype)可以体现这些不同的特点。每个型别都有一套定义好的关于如何创建和清除实例的规则。为了容易区分型别,Symbian系统使用了一个简单的命名规则:类名以大写字母开头(T,C,R或M)。作为类的设计者,你先要考虑这个类的行为,看它到底与哪种型别匹配,一旦确定了它的类型,然后你就可以专注于该类的功能。同样,对一个类的使用者来讲,如果他不熟悉这个类,但类的命名规则可以帮助他弄清你的意图------如何用安全的方式初始化、使用和销毁一个类的对象(object)。下面,我主要讨论不同型别的主要特性。T类T类的行为类似于C++中的内置类型,因此,它们以T作前缀(”T”代表”Type”)。象内置类型一样,它们没有析构方法(destructor),这导致的结果是:T类不能包含具有析构方法的成员变量。所以,一般情况下,T类的成员变量只能是内置类型的数据或者是其它的T类的对象。在某些的情况下T类也可以包含其它对象的指针或引用,不过,这时它们之前是“使用”关系,而不是“拥有”关系(也就是说,这个T类对象并不负责对成员的创建和销毁的工作)。不能拥有外部数据的原因是因为T类没有析构方法。正是由于没有析构方法,T类的对象可以在栈上创建,当程序流程退出函数或产生leave(一种代码异常)的时候,系统自动清除它。即使T类有一个析构方法,在发生异常(在Symbian系统中,异常被称为leave)时Symbian系统也不会调用它,因为leave没有模仿标准C++的抛出异常的做法。T类的对象也可以在堆上创建。但是,应当在调用有可能发生异常的代码之前,将这个对象放入到清除栈(cleanupStack),在发生异常的时候,清除栈(cleanupStack)会释放这个对象。C类这种类都是从CBase派生来的(直接或间接)。//.hfileclassCStudent:publicCBase{public:CStudent(){RDebug::Print(_L(iamastudent));};~CStudent(){RDebug::Print(_L(please,don'tkillme!));}voidSampleFunction(){};private:TIntiCode;TIntiScore;};CBase有两个特点:首先,它有一个虚的析构方法,这样,可以通过CBase指针来删除它的子类。代码如下所示:CBase*pStu=newCStudent();deletepStu;结果:iamastudentplease,don'tkillme!其次,CBase类和它的子类,重载了new操作符,这使得当它在堆上创建的时候,自动初始化为0,也就是说,当它一开始被创建出来的时候,所有的成员变量都被初始化为0,所以您不必在构造方法中去做这件事情。但是,在栈上创建对象时,情况并非这样,因为这时没有用到new操作。这将潜在地导致堆上创建的对象和栈上创建的对象的行为不一致。因此,C类的对象一定要在堆上创建。很明显,当一个堆上的C类对象不再被需要时,我们需要消耗它。一个C类的对象可能以两种方式存在:其它类的指针成员变量或是一个局部的针指变量。在前一种情况下,我们可以在类的析构方法中调用delete来删除它;后一种情况要复杂一些,在调用任何有潜在的异常(leave)的代码之前,要把这个指针放到清除栈(cleanupstack)中,否则有可能发生内存泄露。CBase类声明了私有的拷贝构造方法和赋值操作(=)。这是一个很好的策略,它可以用来防止客户代码不小心地使用了浅拷贝或赋值的方法。由于基类的拷贝构造和赋值是私有的,所以,如果您希望您的类可以能够使用拷贝构造方法,您必须显式地声明和定义拷贝构造方法和赋值操作。但是,考虑到C类的特性,深拷贝可能造成发生异常(leave)的隐患,而您绝对不能让类的构造方法(或析构方法)发生异常(我们在本教程的后面解释原因)。所以,如果您确实需要一个拷贝的方法,那么您可以为类添加一个的可能会发生异常的方法来完成同样的任务,例如:CloneL()或CopyL()。如果您提供的这个类是从CBase派生的,您就不必为了防止客户代码使用有潜在安全问题的“浅”拷贝,而在代码中将这些方法声明为私有的。R类前缀“R”在这里代表资源(Resource),通常是外部资源,例如:文件的句柄(handle)。和C类不同,Symbian系统中不存在一个对应的RBase类,所以一个R类应当有一个构造方法来将它的资源句柄置为0,表明还没有资源和这个新建的对象关联在一起。但是,不要在构造方法中初始化资源句柄,因为这样有可能使构造方法产生异常。R类中常常有类如Open(),Create()或Initialize()这样的方法,它们用来分配资源,设置句柄成员变量的值,并返回错误代码或是产生异常。R类通常也有对应的Close()或Reset()类,用来释放资源,重置句柄的值------表明没有资源和该对象关联。使用R类时,一个常见的错误是忘记调用它的Close()方法(当然,该方法也可以是其它名字,但它经常被命名为Close())或是有一个析构方法释放资源,这会引起资源的泄露。R类通常都很小,除了资源句柄没有其它的成员变量。因为不需要。它通常也没有析构方法,资源的释放都是在Close()方法中进行的。大多数情况下,R类都是作为类的成员变量或局部变量存在的。只有少数情况下,在堆上创建。您必须确保,当程序发后异常的时候,资源能被正确地释放------通常是使用资源栈。如果一个R类是一个堆上的自动变量(相对于成员变量),您一但要保证资源被释放,而且,变量本身也要被释放。typicallybyusingtwopushcalls:CleanupClosePushL(),orasimilarfunction,toensurethattheresourceiscleanedup,andastandardCleanupStack::PushL(TAny*)whichsimplycallsUser::Free()ontheheapcell.R类的成员变量通常都很简单,所以一般不需要深拷贝(bitwisecopy)。R类的拷贝可能会引起混乱(想象一下:如果两个对象同时在一个资源句柄上调用Close()方法,或两个对象都没有释放资源,会发生什么情况?)如果,您想阻止任何对R类的拷贝,您应当声明(但不定义)一个私有的构造方法和赋值操作。M类当提到多继承的时候,它意味着从一个主要的类派生,同时也混杂基它类的功能。前缀M是单词Mixin的首字母。Symbian系统不赞成多继承的做法,因为这个引入额外的复杂性,M类是一个抽象类,它的作用相当于java中的接口(interface)。在Symbian系统中,M类常被用来定义回调接口或者是观察者(observer)类。M类也可以被其它类继承。下面我们给出两个例子。classMAnimal{public:virtualvoidEatL()=0;};classMDomesticAnimal:publicMAnimal{public:virtualvoidNameL()=0;};classCCat:publicCBase,publicMDomesticAnimal{public:virtualvoidEatL(){};//从MAnimal,经过MDomesticAnimal继承virtualvoidNameL(){};//从MDomesticAnimal继承//Otherfunctionsomittedforclarity};上面的例子演示了一个从CBase类和一个M类派生的具体类。而类MDomesticAnimal又是从MAnimal派生的。象接口一样,由于不能被实例化,M类只能有虚(virtual)函数,不能有成员变量和构造方法。但它可以有析构方法,条件是,实现它的具体类必须是从CBase派生的。在定义完类以后,然后可以用使用它。代码如下:CCat*cat1=newCCat;deletecat1;//正确然下面的代码却是错误的。MAnimal*cat2=newCCat;deletecat1;//错误当用M类的指针引用一个对象的时候,如果用delete删除这个指针,则这个M类必须提供一个虚拟的析构方法,否则会出现系统异常(paniccode42)。将MAnimal的代码改写,则上面代码没有问题。classMAnimal{public:virtualvoidEatL()=0;virtual~MAnimal();//增加一个虚的析构方法。};3描述符(descriptor)在Symbian系统中,字符串被称为“描述符”(descriptor),因为它们是自我描述的。在描述符中保存了它所表示的字符串的长度和它的底层的内存布局的信息。描述符比标准C中的字符数组和字符指针要复杂,您可能需要多花些时间来学习和掌握它的用法。关键是,它们的特殊设计使得它们在少量内存的设备上非常有效率,仅用非常少的内存就可以保存自己的长度和内存布局的信息。现在,让我们

1 / 22
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功