|
以下文章的内容基本来自《Using Symbain OS String Descriptors》,在看了《Using Symbain OS String Descriptors》后,颇有一些自己的体会,忍不住在翻译的同时要加些自己的东西,希望原文作者不要见怪。
我现在基本是刚刚接触Symbain,和《Using Symbain OS String Descriptors》的作者那个时候一样,对 ymbian OS的Descriptor很是迷惑不解,尤其是他那些搞来搞去的名字,虽然我已经在我的Blog里写了两篇关于Descriptor的介绍,说句实话,我认为我理解的深度还非常有限。如果你是一个初学者,我觉得首先应该搞清那些搞大不清楚的描述符的类名。要搞清楚这些类名,我觉得应该从以下几点入手:
# Descriptor类的静态继承结构;
# Descripor类的对象在内存中的存储方式;
# Descriptor 类的对象是否可被修改;
事实上,不管他的名字搞来搞去有多搞,名字总是能够反映事物的特征的。比如我小写时代我妈妈给我取的“学名”反映出我是无行缺水,所以每个字都有三点水。常用 Descriptor 包括8个类,可以先来看看老祖宗 TDesC 名字的含义:名字以T开头,表示是一个T类,至于T类是什么东西,可以在我的Blog中找些资料看看;中间是Des,就是Descriptor的缩写;后缀C表示是一个常量 Const。所以从名字中也不难找出共同点,例如TBuf和TBufC 他们中间部分都是Buf,这就说明了他们在内存的存储结构;再如TPtrC和TPtr,他们的中间部分都是ptr,意思是Pointer,说明这两个类都存放了一个指向某段内存的指针。这样对于 HbufC 也不推出它名字所包含的意思。另外还需说明的是,这些存属我个人的推测(未见正规资料有这样的介绍),目的是方便描述符的记忆、比较和使用,如果事实与推测不符,请指出。
下面,是从以上三个方面来说明各个描述符的特征,方便记忆。另外,这里需要特别提出一点,在使用(创建)描述符时,需要密切关注他们的长度,如果长度过长,那么就会发生 Panic。
| 名 称 |
修 改 |
指 针 |
存 储 |
| TDesC |
否 |
否 |
无 |
| TDes |
是 |
否 |
无 |
| TBufCBase |
否 |
否 |
无 |
| TBuf |
是 |
否 |
 |
| TPtr |
是 |
是 |
 |
| TPtrC |
否 |
是 |
 |
| TBufC |
否 |
|
 |
| HBufC |
否 |
|
 |
话说到这里,我建议大家先看一下另外两篇关于描述符的文章,特别是 《Descriptor 存储》,因为下文中会涉及到一些概念的东西。《Descriptor 存储》说到,描述符可以存放在程序二进制码中、栈中、堆中;但是不管怎样,总是存放在内存中的——我以前做Java从来不需要考虑内存的问题,现在学Symbain C++,最好什么时候去弄块内存条,学Symbian 的时候自然要放在桌上,好让自己看到;走路的时候要放在口袋里,随时可以用手摸到;睡觉的时候要放在枕头底下,要压的牢牢的,千万不要发生内存泄露。呵呵,内存对于Symbian 来说太重要了——所以对于描述符的操作始于描述符在内存中的构建。通常的做法是,在使用描述符时,首先使用TBuf或TBufC完成描述符在内存中的构建,如果你要修改则可以利用他们构建可以修改的描述符。
# 使用 TBufC和TBuf:
//创建 _LIT(DES,"我是啊牛!"); TBufC<10> des1(DES); out(des1); TBuf<10> des2(DES); out(des2); // 打印数据成员 console->Printf(_L("len=%d\n"),des2.Length()); //左取两个字符 out(des2.Left(2)); |
# 从 TBufC 或 TBufC 获得 TPtrC
//创建 _LIT(DES,"我是啊牛他爸爸!"); TBufC<10> des1(DES);
TBuf<10> des2(DES);
//获得 TPtrC的两种方法。 TPtrC des3; des3.Set(des1); out(des3);
TPtrC des4(des2); out(des4); |
从TPtrC的使用中,其实也可以估计到其他描述符类型的使用方法,例如TBufC,TBufC没有Set()方法,但是TBufC可以直接用“=”进行赋值。TBufC用于存放文本数据,TBufC8则可以用于存放二进制的数据。TBufC是不可修改的,但是赋值操作却可以更改TBufC中的内容:
//创建 _LIT(DES1,"我是啊牛!");
_LIT(DES2,"我是啊猪他妈妈!");
TBufC<10> des1(DES1); out(des1); des1=DES2; out(des1); des1=DES1; out(des1); |
再强调一次,这个时候一定要注意描述符的长度。
但,如果我要象描述符中间某个位置插入另外的描述符,或者向描述符追加一个字符串呢,这个时候需要把描述符转成TBuf或者TPtr类型。看代码:
//创建 _LIT(DES1,"我是啊牛");
_LIT(DES2,"我是啊猪他妈妈!");
TBufC<10> des1(DES1); TPtrC des2; des2.Set(DES2);
TPtr des3=des1.Des(); //追加 des3.Append(_L("牛!")); out(des3);
TBuf<20> des4(des2);
des4.Replace(5,2,_L("爸爸的妈妈")); out(des4) |
Working with Heap Descriptor HBufC
堆描述符HBufC,当你不确定你的描述符有多少的数据的时候使用。虽然HBufC以C后缀说明是一个不可修改的常量,但是它同样可以有两个方更改其内容。一种修改方法和HBufC一样,使用赋值的方法。另外一种就是通过TPtr。这里有演示代码:
// 方法1:使用 New(), NewL(), or NewLC() // 当前Buf的大小为零 HBufC * Buf = HBufC::NewL(15); console->Printf(_L("Size=%d;len=%d\n"),Buf->Size(),Buf->Length()); //通过赋值改变描述符内容 *Buf=_L("阿牛吃小草。");
out(*Buf); console->Printf(_L("Size=%d;len=%d\n"),Buf->Size(),Buf->Length());
// 方法2:使用已经存在的描述符的 Alloc(), AllocL(), 或 AllocLC() 方法 // 这些方法都返回以现有描述符内容初始化的HBufC指针。 _LIT (KText , "阿牛拉猪屎。");
TBufC<50> CBuf = KText; HBufC * Buf1 = CBuf.AllocL(); out(*Buf1); console->Printf(_L("Size=%d;len=%d\n"),Buf1->Size(),Buf1->Length());
// 改变 HBufC 所指向的内容 _LIT ( KText1 , "啊牛生小牛!"); *Buf1 = KText1; out(*Buf1); console->Printf(_L("Size=%d;len=%d\n"),Buf1->Size(),Buf1->Length());
// 把HBufC转为TPtr型,注意:这个时候,描述符的大小已经发生了改变。 TPtr Pointer = Buf1->Des(); // 进行删除操作 Pointer.Delete(3,1);
out(*Buf1); console->Printf(_L("Size=%d;len=%d;max=%d\n"),Buf1->Size(),Buf1->Length(),Pointer.MaxLength());
//追加 //_LIT ( KNew, "小牛生啊牛。"); _LIT ( KNew, "爽");
Pointer.Append( KNew ); out(*Buf1); console->Printf(_L("Size=%d;len=%d;max=%d\n"),Buf1->Size(),Buf1->Length(),Pointer.MaxLength()) |
点击这里直接下载 VC++6 原程序
|