【发布时间】:2010-11-05 14:56:16
【问题描述】:
我正在使用 MFC 的 CArhive 类为我的应用程序保存项目文件。其中一个类名非常不准确,我想更改它,但只是在任何地方更改名称都会使以前的存档文件无用并出现存档错误。有没有办法在不使之前保存的所有文件失效的情况下更改归档类的名称?
这当然是不使用 typedef 来访问具有新名称的现有类或保留具有旧名称的类的版本来读取存档文件并将读取的对象复制到具有新名称的同一个类.
【问题讨论】:
我正在使用 MFC 的 CArhive 类为我的应用程序保存项目文件。其中一个类名非常不准确,我想更改它,但只是在任何地方更改名称都会使以前的存档文件无用并出现存档错误。有没有办法在不使之前保存的所有文件失效的情况下更改归档类的名称?
这当然是不使用 typedef 来访问具有新名称的现有类或保留具有旧名称的类的版本来读取存档文件并将读取的对象复制到具有新名称的同一个类.
【问题讨论】:
关键点是当您使用DECLARE_SERIAL 和IMPLEMENT_SERIAL 时,一个CRuntimeClass 成员将添加到您的类中,该成员在其m_lpszClassName 字段中包含名称。
这个CRuntimeClass 对象也被添加到由框架维护的列表中,在动态创建类时搜索该列表。
您需要确保CRuntimeClass 对象在m_lpszClassName 中包含您的类的旧名称。
您有两个选择:
覆盖
CRuntimeClass对象设置名称
更改存储在其
m_lpszClassName 字段后
已创建
为此,您需要制作自己的 DECLARE_DYMAMIC、DECLARE_DYNCREATE、DECLARE_SERIAL、IMPLEMENT_DYMAMIC、IMPLEMENT_DYNCREATE 和 IMPLEMENT_SERIAL 版本。
您可以复制并重命名现有的实现。
在您的IMPLEMENT_DYNAMIC 版本中,您需要更改构造CRuntimeClass 的代码,以便使用旧类的名称对其进行初始化。
由于CRuntimeClass 是由静态初始化程序创建的,我认为您不能在您的类中执行此操作。
我认为最好的方法是在您的应用程序的InitInstance 中。
将static char* 变量添加到包含旧类名的应用程序类。
然后,在InitInstance 中,在您班级的CRuntimeClass 中设置m_lpszClassName 字段。
无论哪种方式,首先要做的就是完全熟悉动态创建和序列化的工作方式。
【讨论】:
我选择了第三个选项。我最初将我的一个可序列化类命名为CEvent,这在VC6.0 上似乎不是问题;但在 VS2010 上有一个名为 CEvent 的 MFC 内置类,所以我不得不更改它。
所以,我在调用COleServerDoc::OnOpenDocument之前通过修改旧格式文件来修复它
我只是简单地打开,读取内存,找到CEvent并将其替换为任何其他6个字符(必须相同大小)的类名,写入并保存为新文件名,然后打开并读取新文件,没问题。
无论如何,我正在更改新版本的文件扩展名,所以一切正常。
【讨论】: