串形化与动态创建(Serilize & DynamicCreate)

来源:互联网 发布:恢复原始网卡mac地址 编辑:程序博客网 时间:2024/05/16 09:21

串形化与动态创建(Serilize & DynamicCreate

问题的来源

当知道一个类的名称,比如是“CNode”怎样创建它的对象呢?你可能会用以下的方式:

CString className;

//从文件或屏幕上读取类名到className

CObject* p = new className;

那就大错特错了,没有一个c++编译器支持语言版的动态创建!

 

动态创建

看看MFC动态创建思路吧。

为了使用类型兼容原则,要创建的类必须派生自CObject(这是MFC“黑幕”的基础)。当一个类声明了DECLARE_SERIAL,并实现IMPLEMENT_SERIAL两个宏以后,这个类就拥有一个自己的“名片”——静态成员CRuntimeClass(与CObject一样在MFC中几乎无处不在)。并会自动把自己的“名片”加个一由一串CRuntimeClass组成的“类别型录网”(这名字有点怪,引用侯捷的叫法)。这个“名片”拥有两个重要成员即类名与该类的创建函数。于是只要知道该类的类名就可以在这个“类别型录网”中找到这个类的创建函数了。因为这静态的所以这个名片属于类,下文对象的“片名”就是指类的“片名”。

动态创建在对象串形化(对象的文件读写,由CArchive负责)中可谓是大显神威!

 

串形化

一、对象写过程,相对简单,没有用到动态创建:

1.       写对象“名片”。想想不写“名片”到时候挖出来,谁认识呀!

2.       写对象数据。这是在做“有用功”的时候,是用户自己说的算了。

写过程相关事宜:

为了提高效率,CArchive还在写“名片”时候,做了一些小动作,大概意思是:如果一个类的“片名”已经登记过了,那就没有必要再写一次“名片”了,只是做一个已登记标识。

写名片到底写了什么?

名片里有类名,也有创建函数,都可以写进去吗?不,创建函数在每次加载程序的时候,那个巨大的“类别型录网”会重建,创建函数的地址当然不能确保不变。所以现在创建函数没有参考价值的。只能写一个名字。到时候等“类别型录网”重建完,创建函数安家落户了,我们再用名字去找它。

这个两写动作到底怎么写?

写“片名”是由CRuntimeClass说了算,写对象数据就由对象说了算,类是程序员定义的,就是说程序员说了算。CArchive只是在中间提供组织管理作用用,具体写什么,还是调用CRuntimeClass与类的相关函数完成的。由于CRuntimeClassMFC做死固化了的,所以程序员当然管不了了,也没有必要管,因为它做的不是“有用功”。真正做“有用功”的写对象数据,这里你想怎么写都行。

二、对象读过程,该拿出动态创建的时候了。

写过程告诉我们应该先读对象“片名”,再读取存入的对象数据。写“片名”过程上面已经交代,读“名片”只能获得类名这唯一有用线索。现在这拿着类名,找到“类别型录网”的入口,遍历这个“网”,看看哪个“片名”的类名与现在拿着的类名相同,相同就找到了,用这个“名片”的创建函数,创建一个类对象吧!大功告成!

有那这个类对象,我们才可以读对象数据。因为读对象函数(serialize)要用这个对象调用,这是为什么要创建类对象的原因。

细节问题:(恐怕只有源码才能说清楚):

CArchive为提高效率的方法,使用的标识

“类别型录网”的创建,与入口的查找

补充内容:

使用一个类具有“串形化能力(serializable)”意思就是:可以有太磁盘文件中创建它。

这样的类应该具备的条件:

1.     CObject派生。为使用类型兼容原则,是多态的前提。

2.     添加了DECLARE_SERIAL IMPLEMENT_SERIAL两个宏。为自己打造一个“片名”加入“类别型录网”。

3.     有一个无参构造函数。创建对象时用的。

4.     有一个serialize函数。让MFC调用。