理解Symbian的命名规则
来源:互联网 发布:腾讯视频区淘宝广告 编辑:程序博客网 时间:2024/06/05 17:29
本文最初发表于SpriteLW的博客http://blog.csdn.net/SpriteLW,欢迎转载,但请务必保留原文完整,并保留本声明。
前缀T、C、R、M
T ―― 数据类型,如Tint,Tuint,TReal,也包括typedef和enum
C ―― 派生天CBase类。
R ―― 资源类。如RFile类,RThread类
M ―― 接口类。M代表Mixin
后缀为“L”和“LC”的函数
表示该函数有可能有“异常”抛出(L表示Leave,后面有讲解),可是这个异常不同C++的异常,是Symbian自己发明的异常。Symbian OS的异常退出/陷阱方法与C++的抛出/捕获方法相比,更轻量级,也更有效。
Symbian的异常处理机制
以下是Symbian异常退出/陷阱示例:
void fooBarL()
{
TInt rc;
rc = SomeFunction();
if(rc)
{
User::Leave(KAnError);//leave被调用
}
//如果Leave没有被调用,则运行以下代码
...
}
void MyFunctionL()
{
....
fooBarL();
//如果Leave没有在fooBarL()里被执行,则继续往下运行
...
}
void StartHere()
{
TInt LeaveError;
TRAP(LeaveError,MyFunctionL());
if(LeaveError)
{
//处理错误
}
//继续运行
...
}
{
TInt rc;
rc = SomeFunction();
if(rc)
{
User::Leave(KAnError);//leave被调用
}
//如果Leave没有被调用,则运行以下代码
...
}
void MyFunctionL()
{
....
fooBarL();
//如果Leave没有在fooBarL()里被执行,则继续往下运行
...
}
void StartHere()
{
TInt LeaveError;
TRAP(LeaveError,MyFunctionL());
if(LeaveError)
{
//处理错误
}
//继续运行
...
}
程序从StartHere开始,通过TRAP宏调用MyFunctionL(),而 MyFunctionL()调用fooBarL()(没有TRAP宏)。如果在fooBarL中SomeFunction失败,则调用系统静态API函数 User::Leave(),这将使fooBarL即刻停止执行,并返回到MyFunctionL(),由于MyFunctionL()调用 fooBarL时,没有定义一个陷阱处理器(TRAP),则MyFunctionL调用fooBarL函数后立即退出,并向它的调用函数 StartHere传送异常。
由于StartHere()使用TRAP宏调用MyFunctionL(),所以StartHere不会自动退出,相反,
异常退出码(KAnError)写入TRAP宏的第一个参数(LeaveError),并继续运行。
TRAP宏和TRAPD宏
TRAP宏的原型为TRAP(TInt,Function),第一个参数必须在前面有定义,如
TInt LeaveError;
TRAP(LeaveError,MyFunctionL());
TRAP(LeaveError,MyFunctionL());
如果MyFunctionL由于异常退出,则LeaveError就会被设置成传递给User::Leave()的值,如果没有发生异常,则LeaveError被设置为KErrNone(0)。
TRAP的一个变化版本是TRAPD(D代表Declare),所以上面代码等阶于
TRAPD(LeaveError,MyFunctionL());
异常退出函数
异常退出函数有多个版本:
User::Leave(code);//简单Leave
User::LeaveNoMemory();//等价于Leave(KErrNoMemory)
User::LeaveIfError(error);//如果error小于0,则调用Leave(error)
User::LeaveIfNull(TAny *ptr);//如果ptr为Null,则调用Leave(KErrNoMemory)
User::LeaveNoMemory();//等价于Leave(KErrNoMemory)
User::LeaveIfError(error);//如果error小于0,则调用Leave(error)
User::LeaveIfNull(TAny *ptr);//如果ptr为Null,则调用Leave(KErrNoMemory)
后缀为“L”函数的意义:就是表示函数内含有“Leave**”
下面讲解后缀为“LC”函数的意义
请看以下代码
void MyFunction
{
TInt *buff;
buff = new TInt;
...
funcL();
...
delete buff;
}
{
TInt *buff;
buff = new TInt;
...
funcL();
...
delete buff;
}
Symbian采用了一种机制――清理栈,请看以下代码
void FuncL()
{
CMyObject *myObj = new CMyObject;
CleanupStack::PushL(myObj);
TInt *buff = new TInt[1000];
CleanupStack::PushL(buff);
DoSomethingL();
Cleanupack::Pop(2);
delete myObject;
delete buff;
}
{
CMyObject *myObj = new CMyObject;
CleanupStack::PushL(myObj);
TInt *buff = new TInt[1000];
CleanupStack::PushL(buff);
DoSomethingL();
Cleanupack::Pop(2);
delete myObject;
delete buff;
}
如果DoSomethingL()异常退出,则FuncL返回到调用函数之前,释放清理本中的每个指针(在这里是myObj和buff)。
如果DoSomethingL()没有异常退出,则要通过CleanupStack::Pop(2)弹出两个项。
正如你所看到的CleanupStack::PushL也包含“L”,但是可以确信PushL只有在项被压入清理栈中后,才异常退出,所以即使PushL失败时,清理栈中的项也能被清除。
Pop函数的一个变种是CleanupStack::PopAndDestory(),这个函数可以替换ClearupStack::Pop(2)和两条delete
PushL的方法
PushL(CBase *)//在清除时会使用delete删除该对象,由于CBase类的析构函数是虚函数,因此调用了派生类的析构函数
PushL(TAny *)//非CBase类即TAny类,则不调用delete,而改为User::Free()函数。
PushL(TAny *)//非CBase类即TAny类,则不调用delete,而改为User::Free()函数。
LC函数
以LC结尾的函数提供了一个附加的便利――在成功完成后,返回值会被压入清理栈中,但别忘记弹出清理栈中的指针。如下面代码
void FuncL
{
TInt *buff;
buff = User::AllocLC(1000);
.....
FooL();
CleanupStack::PopAndDestroy();
}
{
TInt *buff;
buff = User::AllocLC(1000);
.....
FooL();
CleanupStack::PopAndDestroy();
}
双阶段构造函数
Symbian有一个特别的语法:
CMyObject *obj = new(ELeave)CMyObject;
它是new运算符的重载,对于一条传统的new语句(CMyObject *obj = new CMyObject) 来说,编译器以这样的方式调用内置的new函数原型:new(TInt)――TInt参数是对象的大小。但是如果在new后加ELeave,编译器则改为 这样的调用函数原型:new(TInt,TLeave),TInt是对象的大小,而ELeave是参数ELeave的数据类型,ELeave只是一个哑元 变量,它的目的是引起该重载new的调用,Symbian OS实现了这个重载new函数是用于在内存分配失败是时异常退出。
现在有一种情形:如果在构造函数本身发生异常退出呢?这是Symbian OS中的一个问题,在new运算符函数分配内存后,就立即(在后台)调用构造函数,没有机会让程序员把指向已分配内存的指针压入清理栈。因此,如果在构造期间发生异常退出,就会得到一个“野指针”。
Symbian对应这个问题的策略是“双阶构造函数”,类中提供一个名为ContructL()的方法用来完成对象的构造(成员的堆分配)。以下是在Symbian中常见的语法:
CMyObj* CMyObj::NewL()
{
CMyObj *self = NewLC();
CleanupStack::Pop();//调用LC函数后,要负责弹出操作
return self;
}
CMyObj* CMyObj::NewLC()
{
CMyObj *self = new(ELeave)CMyObj;
CleanupStack::PushL(self);//LC函数要负责将指针压入清理栈
self->ConstructL();//构造内部成员
return self;
}
{
CMyObj *self = NewLC();
CleanupStack::Pop();//调用LC函数后,要负责弹出操作
return self;
}
CMyObj* CMyObj::NewLC()
{
CMyObj *self = new(ELeave)CMyObj;
CleanupStack::PushL(self);//LC函数要负责将指针压入清理栈
self->ConstructL();//构造内部成员
return self;
}
至此,Symbian最重要的关键字解释已完结,理解了上述规则对日后的开发大有帮助。
- 理解Symbian的命名规则
- 理解Symbian的命名规则
- Symbian的命名规则
- symbian 命名规则
- Symbian命名规则
- Symbian C++命名规则
- Symbian OS C++命名规则
- Symbian手记【一】—— 命名规则
- 对java变量名的命名规则的理解
- Symbian 命名空间的应用
- 数据库命名的规则!
- MySQL的命名规则
- Java的命名规则
- ASP的命名规则
- C++的命名规则
- 编程的命名规则
- 我的命名规则
- ARM的命名规则
- window.opener.location.reload()的使用
- js 关于this的一些语法问题
- 《人生若只如初见——古典诗词的美丽与哀愁》--安意如
- 有关hibernate在ecplise下生成maping,出现错误 an internal error occurred during :"Generating Artifacts"
- Perl Medic: Transforming Legacy Code by Peter J. Scott
- 理解Symbian的命名规则
- 时间格式的设定
- asp.net2.0程序的发布
- Pro Perl Parsing (Pro) by Christopher M. Frenz
- BP网络之C#实现
- Beginning Perl Web Development: From Novice to Professional
- csdn首页的那个新闻,blog,论坛,图书的tab签的做法,滑动门技术
- java实现数据库序号(流水号)
- 二○○七网络新动向:博客集体降温 竞办电子杂志