//
// 这是我的第二篇博文,开始学习Symbian c++
// 同大家一起努力
// 谨以此文献给我的最爱 YY女孩(YY 可别想坏了哦)
//
// -----------------------------------------------------------------
每一个初学Symbian c++的同学肯定和我一样迷茫,那我们就一起来学习吧!
我用的环境是Carbide c++V2.0
其实个人认为Symbian最难入门的是那些从来没见过的数据类型,非常头痛,下面是我找到的数据类型
表2-1 Symbian OS的基本数据类型
(发现下面这些数据都是T开头的,对了学习SC++,对考都和结尾要留心)
数 据 类 型 | 描 述 | C++内置类型 |
TInt | 有符号整数。在所有实现中保证数据至少为32位 | signed int |
TUint | 无符号整数。在所有实现中保证数据至少为32位 | unsigned int |
TInt32、TInt16、 | 32位、16位和8位的有符号整数 | long int、short int、singed char |
|
|
|
TUint32、TUint16 TUint8 | 32位、16位和8位的无符号整数 | unsigned long int、unsigned short int、unsigned char |
TInt64 | 64位整数 | long long |
TUint64 | 64位无符号整数 | unsigned long long |
TText | 文本型,又细分为TText8和TText16,内部引用都是TText16 | unsigned short int |
TText8 TText16 | 8位和16位无符号文本 | unsigned short int unsigned char |
TReal32 | 32位浮点数 | float |
TReal、TReal64 | 64位浮点数 | double |
TBool | 布尔型 | int (这里是Int ?) |
TAny | 指针型 | void |
如果想了解更仔细请参考 http://book.csdn.net/bookfiles/1240/100124036909.shtml
除了以上的基本数据类型,SC++中的String型也是拦路虎之一;
描述符 SC++中的String型
描述符是 Symbian OS中用到的字符串类。之所以这样称呼它们,是因为它们是自描述的字符串。也就是说,描述符不仅包含它所描述的字符串数据的长度,还包含了类型信息,以区分描述符数据在内存中不同的结构。描述符可以防止缓存溢出,它并不使用NULL结束符作为字符串的结尾。(这个也是c++的特点,C中才会有NULL来结束)
描述符的应用从最底层向上贯穿于整个操作系统,而且它们被设计得非常有效率,使用最小的内存空间但又足够存储数据,并同时可以全面描述其长度和位置。描述符可作为字符串并包含字符数据。同时它们还可以用来操作二进制数据,因为它们不需要用NULL作为结尾字符来确定长度。
表3-2 对描述符类型的总结
名 称 | 是否可修改 | 等 价 C | 类 型 | 说 明 |
TDesC | 否 | n/a | 不可实例化 | 其他所有描述符的基类(字面描述符除外) |
TDes | 是 | n/a | 不可实例化 | 所有可修改描述符的基类 |
TPtrC | 否 | const char* (数据不被描述符所 “拥有”) | 指针 | 数据与描述符是分开存储的,即描述符并不知道数据的存储位置 |
TPtr | 是 | char * (数据不被描述符所 “拥有”) | 指针 | 数据与描述符是分开存储的,即描述符并不知道数据的存储位置 |
TBufC | 可间接修改 | const char[] | 栈缓存 | 瘦模板的大小在编译时才确定 |
TBuf | 是 | const[] | 栈缓存 | 瘦模板的大小在编译时才确定 |
HBufC | 可间接修改 | const char* (可“拥有”数据) | 堆缓存 | 用于修改频繁的动态数据存储 |
RBuf | 是 | char* (可“拥有”数据) | 堆缓存 | 用于可修改的动态数据存储 |
TLitC | 否 | static const char[] | 字面描述符 | 构建在ROM里 |
TDes定义了一组操作可变字符串数据的方法,包括那些对描述符进行扩充、填充以及格式化的操作。所有改变描述符的操作代码都由TDes来实现,并且可被其派生类继承。在Symbian Developer Library(这个书友谁可以给个连下载下,谢谢)里有对可变及不可变描述符的基类API方法进行全面描述的相关文档。
描述符基类TDesC和TDes实现了所有通用的描述符操作代码,但是它们不能被实例化。
指针型描述符:TPtrC和TPtr
觉得没什么好讲的,就是指针型,没能拥有真的内存空间,末尾是C的是常量指针,不能修改指向的内容,但是可以修改指针的指向,而TPtr是没有限制的,可以改变指向的内存地址的数据。
基于栈缓存的描述符TBufC和TBuf 在上面的表中已有说明,相当于数组
动态描述符:HBufC和RBuf
HBufC和RBuf描述符类可用于在编译期间大小不能确定的动态字符串数据(比如网络接收数据),以及那些对栈内存来说过于庞大的数据。这些类被用于在C中需要使用malloc来分配数据的地方。
HBufC
类HBufC8和HBufC16(其对应的中立类 HBufC被typedef定义为HBufC16)提供了一组静态的NewL()函数,以便在堆上创建描述符。这些方法在没有足够内存可用的情况下会异常退出。所有的堆缓存必须使用这些方法来建立,或者也可以使用TdesC类的Alloc()或AllocL()方法来建立,这两个方法都可以从已存在的描述符中建立出HBufC的一个副本。一旦描述符以其所需的大小建立后,当它又需要更多空间时就不会自动重新分配大小,额外的内存需要使用ReAlloc() 或ReAllocL()方法来分配。
作为一个类名中以C字符为后缀的类,HBufC描述符不能被直接改变,但此类提供的赋值操作符允许替换缓存中的整个内容。要想在运行期间改变一个HBufC对象,应该首先从HBufC::Des()方法中获得一个可变的描述符指针TPtr。
_LIT(KTestBuffer, "Heap Based");
(这个是个内置类型,相当于#Define KTestBuffer “Heap Based“)
// create a heap-based descriptor and place it on cleanup stack
HBufC* pHeap = HBufC::NewLC(32);
// create a pointer descriptor around pHeap
TPtr ptr(pHeap->Des());//把值赋给指针
// modify pHeap indirectly via ptr
ptr = KTestBuffer; //这里有点费解,KTestBuffer难道也是指针?
...
// clean up
CleanupStack::PopAndDestroy(pHeap);
RBuf
RBuf类从TDes继承而来,所以RBuf类的对象可以不用创建一个指向其数据的TPtr以修改其内容,这使得它要比HBufC更好用。在实例化时,RBuf对象既可以自己分配缓存,也可以取得先前分配好的内存或已有的堆描述符的控制权。为了与本章开始时的Symbian OS命名习惯保持一致,RBuf类没有被叫做HBufC,因为与HBufC不同的是,RBuf不是直接在堆上创建的。RBuf描述符通常在栈上创建,并且拥有一个它需要负责清除的指向堆上资源的指针。
在内部,RBuf表现为以下两种方式之一:
● 与TPtr直接指向内存中存储的描述符数据类似,RBuf对象分配或取得描述符数据的拥有权。
● 作为一个指向已存在堆描述符的指针——HBufC*。RBuf对象取得HBufC的拥有权,并且拥有一个指向包含完整描述符对象的指针(完整是相对于前面所讲的指向一个简单数据块的指针而言的)。
然而这都是透明的,不需要去了解一个特定的RBuf对象在内部是怎么描述的。使用此描述符类也相当直观,就像使用其他的描述符类一样,使用从TDes和TDesC继承而来的方法即可。
RBuf对于Symbian OS来说加入的时间相对较短,它最先出现在Symbian OS v8.1的文档中,并且被广泛应用于为基于Symbian OS v9或其后版本的手机所设计的软件中。
RBuf在许多最初的例子代码中基本没有用到,但是它却是您在需要为容纳经常改变的数据而动态分配缓存时比起 HBufC来说更为容易的类。
HBufC对于那些需要为容纳不会改变的数据而动态分配的描述符来说还是相当理想的;也就是说如果是不改变数据的访问的话,它还是不错的。
使用RBuf
RBuf对象可以通过Create()、CreateMax()或CreateL()方法来创建,并可以指定所能存储的描述符数据的最大长度。也可以先实例化一个RBuf,然后将另一个描述符的内容复制进去,如下所示:
RBuf myRBuf;
LIT(KHelloRBuf, "Hello RBuf!"); // Literal descriptor
myRBuf.CreateL(KHelloRBuf());
CreateL()为RBuf分配了一段缓存来引用。如果RBuf之前拥有一段缓存,由于CreateL()在分配新的缓存引用前不会将其清除,所以必须先调用Close()来释放先前拥有的内存。
另一种方法是先实例化RBuf,然后再用Assign()方法取得一段已存在内存的所有权。
// Taking ownership of HBufC
HBufC* myHBufC = HBufC::NewL(20);
RBuf myRBuf;
myRBuf.Assign(myHBufC);
Assign()也会使RBuf已经拥有的数据孤立,所以在重新指定之前要调用Close()来避免内存泄漏。
在特定操作需要更多内存时,RBuf类不会去操纵缓存的大小或者为它重新分配内存。如果一个可变的方法——比如Append()——在没有足够可用内存时被RBuf对象调用,那么将会出现一个严重错误。作为程序员,您应该为保证RBuf对象在其缓存内有足够空间而负责,并可以在需要时使用ReAllocL()方法:
// myRBuf is the buffer to be resized e.g. for an Append() operation
myRBuf.CleanupClosePushL(); // push onto cleanup stack for leave-safety
myRBuf.ReAllocL(newLength); // extend to newLength
CleanupStack::Pop(); // remove from cleanup stack
注意上面的例子用到了CleanupClosePushL(),来把RBuf类推入清除栈。清除工作在调用Close()(或者是调用CleanupStack::PopAndDestroy(),当RBuf是通过调用RBuf::
Cleanup-ClosePushL()被推入清除栈时)时开始,这对于其他R类来说很常见。
字面描述符
字面描述符与其他描述符类型略有不同。它们相当于C 中的static const char[],并且由于它们是常量,所以可以被构建在ROM里以便在运行时节省内存。一组e32def.h中的宏可以用来定义Symbian OS的两种不同类型的字面文字,_LIT和_L。
因为更具效率,所以_LIT宏更适合用作Symbian OS的字面文字。它的典型用法如下:
_LIT(KSymbianOS, "Symbian OS");(注意 K开头一般都是常量)
_LIT宏在程序的二进制代码中构建了一个名为KSymbianOS的TLitC16类型的对象,存储了相应的字符串(本例中是“Symbian OS”)。显式的宏定义_LIT8和_LIT16行为相似,不过_LIT8构建的是TLitC8类型的窄字符串。
TLitC8和TLitC16不是从TDesC8和TDesC16继承而来的,但是它们拥有和TBufC8及TBufC16相同的二进制布局。这就保证了所有可以传入TDesC的地方也可以使用这些类型的对象。
Symbian OS还定义了表示空字符串的字面文字。有三种不同的null描述符,定义如下:
// Build independent:
_LIT(KNULLDesC,"");
// 8-bit for narrow strings:
_LIT8(KNULLDesC8,"");
// 16-bit for Unicode strings:
_LIT16(KNULLDesC16,"");
虽然在测试代码中(其对内存的使用稍微宽松些)还有可能用到_L宏,但是在产品代码中已经不推荐使用它了。它可以在如下所示的一行代码里定义并使用:
TBuf<10> KSymbianBuf(_L("Symbian OS"));
如有错误 请斧正 谅解 博文完