首 页 | 新 闻 | Symbian | Android| Windows Mobile | J2ME | 下载中心 | 游戏策划招聘与求职 | 购书指南 | 视频教程
您现在的位置: 开发视界 >> Symbian >> Symbian开发 >> 正文
Symbian类里的extension和reserved
作者:佚名    文章来源:转载    更新时间:2007-6-11 9:06:49
Symbian的很多类里头,类的定义是这样的:

//forward class declaration
class CMyClassExtension;

class CMyClass : ....
{
public:
    CMyClass();
//.....

private:
   CMyClassExtension * iExtension ;  // xxx used for extension class pointer.

private:
    TInt iReserved_1;
    TInt iReserved_2;

private:
    friend class CMyClassExtension;
}

这里的 iExtension, iReserved_1,iReserved_2,是个非常特别的设计。
我们调用 CMyClass的时候,并不会使用这些 extension和reserved。
也就是说,这些东西我们作为SDK使用者是不关心的。

为什么会有这些东西呢?其实现在,有很多类的 extension 和 reserved变量,
Symbian SDK自己也没有用到。但是我们不得不佩服,这的确是个非常巧妙的设计。

所有缘由,来自于一个概念: 二进制兼容。

二进制兼容的意思,就是SDK升级了,我们以前开发并且已经发布的程序,还可以
在新的SDK上运行。严格说来,当SDK升级的时候,可能需要旧的应用程序这么
作:
1 -- 什么也不做,  照样运行
2 -- 只是重新编译,就能运行
3 -- 得修改代码,  才能运行

其中的1,就满足二进制兼容。但是 2,3都打破了二进制兼容。

举一个例子:

//应用程序的代码,已经发行的产品.
void CUserClass::Function()
{
    TOneClass one;
    //use "one" to do something.       
}

如果 TOneClass 的大小由于SDK升级而被改变了,这回带来什么结果呢?
因为 Function()在编译期间,编译器就已经给这个函数分配了栈空间。
"one" 是分配的 老的 SDK中 TOneClass的大小(sizeof(TOneClass)).
可是 SDK 升级之后,TOneClass的大小改变了,那么在新的SDK上运行的
时候,"one" 分配的栈空间还是老版本 TOneClass的大小。可是真正运行
的时候,应用程序却不得不使用新版本的TOneClass.这样,栈的空间就被
破坏了。比如,以前的版本中,编译器是分配30个字节给one.可是在新的
SDK 中,因为 TOneClass被添加了一个 变量,运行的时候,发现30个
自己并不能容纳 TOneClass.

Symbian 要求 T类基本上不改变大小,即使 SDK升级了。

C类也是一样。虽然C类是使用new来分配在堆上的,但我们不能指望 C类的
调用着不使用 sizeof(CMyClass). 所以C类的大小也不能改变。

这就是为什么有 extension和reserved. 一些C类在设计的时候,就考虑
到了因为升级可能会添加一些函数或者成员数据。新添加的函数会放在
CMyClassExtension中间实现,而新的数据成员会由 reserved 作为
指针来指向它。虽然 reserved一般声明为 TInt,但我们也知道 TInt
可以保存一个指针指向堆里的数据。

对于 extension,其实在旧的SDK中,根本没有定义 CMyClassExtension.
只是前向声明,告诉 CMyClass,会有这么个类,但这个类是什么,没有
任何其他地方定义它,也就是没有这样的东西:

class CMyClassExtension : public CBase
{
public:
    .....  
}

对C++来讲,前向声明已经足够了,因为在CMyClass使用的是指针,而不是对象.
如果CMyClass里头是这么定义的:
CMyClassExtension extension;
那么必须得定义真实的 CMyClassExtension 类了.

这里使用的是指针,所以旧SDK根本就不会定义它和实现它.
如果因为升级SDK需要添加一些函数给CMyClass,那么可以把这些函数放在
CMyClassExtension里头了.

比如:
class CMyClassExtension : public CBase
{
public:
   ....
   DoNewFunciton1();
   DoNewFunciton2();
}

因为CMyClassExension通常会被声明为 CMyClass的friend.(看开头的
CMyClass定义).所以它访问CMyClass的所有变量和函数是没有问题的.在
CMyClassExtension里头实现所有的新功能.


如果新的 SDK 的确更改了很多东西,那么打破二进制兼容是不可避免的.
这个时候 symbian 会声明 新版本的SDK打破了二进制兼容.这样其实很有
好处,Symbian是嵌入式系统,它不会让自己的代码因为兼容老系统而越
来越庞大.Windows系统的就是一个越来越庞大的例子.
相关文章:
在没有ui的程序中捕获所有的key事件
Symbian应用程序中如何备份和载入
播放WAV文件
Symbian程序中的观察者模式
S60平台:Bluetooth API开发伙伴指南——搜索和发布
如何在SYMBIAN60中编写DLL
C++ 基类和派生类
定义类的问题
 

站点地图 | 加入收藏 | 联系站长 | 广告服务 |
QQ:280529124  Tel:0592-8271361 辽ICP备05021703号