MFC源码:#define DECLARE_DYNAMIC(class_name) \public: \static const CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const; \

#define _DECLARE_DYNAMIC(class_name) \

public: \

static CRuntimeClass class##class_name; \

virtual CRuntimeClass* GetRuntimeClass() const; \

// not serializable, but dynamically constructable

#define DECLARE_DYNCREATE(class_name) \

DECLARE_DYNAMIC(class_name) \

static CObject* PASCAL CreateObject();

#define _DECLARE_DYNCREATE(class_name) \

_DECLARE_DYNAMIC(class_name) \

static CObject* PASCAL CreateObject();

#define DECLARE_SERIAL(class_name) \

_DECLARE_DYNCREATE(class_name) \

AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);

#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) \

AFX_COMDAT const CRuntimeClass class_name::class##class_name = { \

#class_name, sizeof(class class_name), wSchema, pfnNew, \

RUNTIME_CLASS(base_class_name), NULL, class_init }; \

CRuntimeClass* class_name::GetRuntimeClass() const \

{ return RUNTIME_CLASS(class_name); }

#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) \

AFX_COMDAT CRuntimeClass class_name::class##class_name = { \

#class_name, sizeof(class class_name), wSchema, pfnNew, \

RUNTIME_CLASS(base_class_name), NULL, class_init }; \

CRuntimeClass* class_name::GetRuntimeClass() const \

{ return RUNTIME_CLASS(class_name); }

#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \

IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL, NULL)

#define IMPLEMENT_DYNCREATE(class_name, base_class_name) \

CObject* PASCAL class_name::CreateObject() \

{ return new class_name; } \

IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, \

class_name::CreateObject, NULL)

#define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) \

CObject* PASCAL class_name::CreateObject() \

{ return new class_name; } \

extern AFX_CLASSINIT _init_##class_name; \

_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, \

class_name::CreateObject, &_init_##class_name) \

AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); \

CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) \

{ pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); \

return ar; }

以下是我(fyl)对这些宏的理解:

IMPLEMENT_RUNTIMECLASS中定义了静态CRuntimeClass对象,并赋予当前类与基类的信息 ,当前类类名及版本号wSchema,动态创建当前类对象的函数地址CreateObject等。

它实现了基类与派生类之间的连接,在MFC类层次之间形成了树形层次的结构,所以可以在此基础上实现动态类 型的识别IsKindOf:

while (pClassThis != NULL)

{

if (pClassThis == pBaseClass)

return TRUE;

if (pClassThis->m_pfnGetBaseClass == NULL)

return FALSE;

pClassThis = (*pClassThis->m_pfnGetBaseClass)();

}

DECLARE_DYNAMIC仅提供动态类型的识别,只需要基类与派生类之间的连接,不需要其它信息,所以IMPLEMENT_DYNAMIC调用的IMPLEMENT_RUNTIMECLASS版本号:0xFFFF(表示无效), 动态创建当前类对象的函数地址:NULL。

DECLARE_DYNCREATE增加了动态创建,所以IMPLEMENT_DYNCREATE增加了动态创建当前类对象的函数CreateObject,并传递给IMPLEMENT_RUNTIMECLASS。

DECLARE_SERIAL实现串行化(保存与读取),不同版本的保存与读取是可能存在不同的,所以需要版本号,所以IMPLEMENT_SERIAL增加了版本号传递;

另外,在读取时,读到class信息时需要判断是那个类后才可以动态生成,所以IMPLEMENT_SERIAL中增加了AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name))。

AFX_CLASSINIT是结构的定义:

struct AFX_CLASSINIT

{ AFX_CLASSINIT(CRuntimeClass* pNewClass); };

仅有一个构造函数,定义如下:

AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass* pNewClass)

{

pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;

CRuntimeClass::pFirstClass = pNewClass;

}

此构造函数负责 linked list 的串接工作。在MFC类中依靠AFX_CLASSINIT在原有树形的结构上增加了链表,链表将所有包含*_SERIAL对的MFC类串接后形成一个表。所以读到class信息时在此链表查询即可!

问题1(主要问题):

*_SERIAL中增加了friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);

但我没有使用它时也可以串行化!

CTrip是可串行化的类.操作如下:

头文件中用_DECLARE_DYNCREATE(CTrip)替换DECLARE_SERIAL

源文件中用CObject* PASCAL CTrip::CreateObject() \

{ return new CTrip; } \

_IMPLEMENT_RUNTIMECLASS(CTrip, CObject, 2, \

CTrip::CreateObject, NULL)\

AFX_CLASSINIT _init_CTrip(RUNTIME_CLASS(CTrip));

替换IMPLEMENT_SERIAL!

替换后CTrip同样可以完成串行化的工作?

在源文件中增加CArchive& AFXAPI operator>>(CArchive& ar, CTrip* &pOb) \

{ pOb = (CTrip*) ar.ReadObject(RUNTIME_CLASS(CTrip)); \

return ar; },并在此处设置断点,但是始终不进入,说明没有用到?

问题2:

struct CRuntimeClass

{

mfc只有doc才能序列化吗_MFC序列化-IMPLEMENT_SERIAL(...)相关推荐

  1. Java序列化闲聊:序列化和Json

    前言 其实我挺纠结的,在纠结到底要不要写这个模块的博客,因为序列化这个模块说简单,按照一些人的说法,其实也就是调两个函数的事情,说困难,铺开就让人感觉范围很广. 序列化 什么是序列化,我们在编程的时候 ...

  2. Java中 byte[]数组序列化和fastjson序列化区别

    Java中 byte[]数组序列化和fastjson序列化区别 Java中,对于对象可以通过序列化成byte数组或者序列化成json形式,这里做下两者的对比. 首先看下实现方式: 1 byte数组序列 ...

  3. java序列化流_java 序列化流与反序列化流

    一 对象序列化流ObjectOutputStream ObjectOutputStream 将Java对象的基本数据类型和图形写入OutputStream.可以使用ObjectInputStream ...

  4. Java序列化——JDK序列化与Json序列化

    Java原生序列化 Java原生序列化我们可能会了解的比较多,Java类通过实现Serializable接口来实现该类对象的序列化,这个接口非常特殊,没有任何方法,只起标识作用.Java序列化保留了对 ...

  5. java 对象怎么序列化,java对象序列化总结

    java对象序列化小结 百度百科上介绍序列化是这样的: 序列化 (Serialization): 将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储 ...

  6. 解决Python自带的json序列化工具不能序列化datetime类型数据问题

    解决Python自带的json序列化工具不能序列化datetime类型数据问题 参考文章: (1)解决Python自带的json序列化工具不能序列化datetime类型数据问题 (2)https:// ...

  7. Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑

    前言 上一篇已经介绍了优雅的操作Redis: [小家Spring]Spring Boot中使用RedisTemplate优雅的操作Redis,并且解决RedisTemplate泛型注入的问题.本篇着重 ...

  8. json 序列化 java_Java JSON序列化杂谈

    在C#中序列化是比较容易的,如果不用第三方的类库,那么C#提供的两个对象也够我们使用,一般的操作是定义一个不含有方法的类,这个类里面定义了要序列化的对象的属性,因为我C#用的比较多,这里直接给出泛型, ...

  9. java get方法不序列化_java常用序列化与反序列化方法

    序列化工具类 序列化即将对象序列化为字节数组,反序列化就是将字节数组恢复成对象. 主要的目的是方便传输和存储. 序列化工具类: public class SerializeUtil { private ...

最新文章

  1. android 收不到短信广播,android – 短信广播接收器没有得到textmessage
  2. 模型训练 准确率下降_手写批量线性回归算法:在Python3中梯度下降方法实现模型训练
  3. 从 Alpha 到 Beta,这次是 New mPaaS
  4. sql 除以_使用SQL分析游戏运营情况
  5. hdu3468 Treasure Hunting 二分匹配
  6. CAD(计算机辅助设计)
  7. XLN Audio Addictive Trigger for Mac(智能鼓音替换工具)
  8. 游戏网络编程书籍推荐
  9. l360清零软件无响应_爱普生Epson L360 清零软件
  10. svn 服务端与客户端安装教程 windows
  11. ssm医院人事管理系统设计与实现 毕业设计源码111151
  12. 2008年南京等5城市将升格直辖市
  13. 空之轨迹手游服务器维护,空之轨迹7月9日临时维护公告_空之轨迹7月9日更新了什么_玩游戏网...
  14. signal 11 定位
  15. 力扣(LeetCode)怎么刷题,以排序算法为例
  16. LeetCode 213. House Robber II(小偷游戏)
  17. 安卓读取U盘容量信息,支持低版本API
  18. C#语言实例源码系列-实现屏幕放大器和取色
  19. unigui独立应用部署在电信云上的步骤
  20. 初级开发者福音:手把手教你实现数字滚动效果~

热门文章

  1. R语言使用ggplot2包使用geom_dotplot函数绘制分组点图(自定义填充色)实战(dot plot)
  2. R语言威尔考克森秩和统计分布函数Wilcoxon rank Sum Statistic Distribution(dwilcox, pwilcox, qwilcox rwilcox)实战
  3. Scala error: type mismatch; found : java.util.List[?0] required: java.util.List[B]
  4. stat_count() must not be used with a y aesthetic
  5. 惠普计算机电源怎么设置充电,惠普电脑怎么用外接电源时不用电池怎样设置的...
  6. python 存redis失败无提示_Python Redis日志错误
  7. desc mysql 连表查询_Mysql连表查询
  8. android 手机 吉字节,Java 数据类型05Android开发小典
  9. 组合数函数-快速提取所有可能的组合数
  10. 基因课 15天入门生物信息(2021年) 第三天 Linux基础命令(3)