基于MFC实现类的序列化详解

序列化是将程序中的对象以一种二进制格式存储到存储设备中(例如文本/数据库等),以实现“永生”或随意“流动”

首先定义一个要序列化的类people,其属性有age、weight、height。

#pragma once

class people {
public:
    int age;
    int weight;
    int height;
};

定义好后将该类添加到  项目名view.h  的类中,作为其属性,并且是指针类型

将需要存取的类实现序列化

1.序列化的类必须从CObject派生,或是从CObject的派生类派生

#pragma once
//导入#include<afx.h>头文件,使类能继承CObject
#include<afx.h>

class people :public CObject {

public:
    int age;
    int weight;
    int height;
};

2.为该类定义一个不带参数的构造函数

3.在类声明中使用DECLARE_SERIAL(类名)宏

#pragma once
#include<afx.h>

class people :public CObject {
public:
    DECLARE_SERIAL(people);
    people();
public:
    int age;
    int weight;
    int height;
};

4.在类的实现中添加IMPLEMENT_SERIAL(类名,父类名,版本号)宏

#include "pch.h"
#include "people.h"

//第一个参数是类的名字,第二个参数是父类名字,第三个参数是版本号(一般版本号从1开始)
IMPLEMENT_SERIAL(people, CObject, 1);

people::people()
{
}

5.在类的实现中,通过类向导添加Serialize虚函数(也可也手写)

MFC提供了CArchive类可以将对象数据保存到永久设备,比如磁盘文件。当应用程序重新启动后,CArchive类可以帮助我们从磁盘文件读取这些数据,然后在内存中重新构建对应的对象;这样就使得我们的对象数据永久存在,该过程称之为序列化(或者串行化)。

void people::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {    // storing code
    }
    else
    {    // loading code
    }
}

CArchive类重载了输入输出运算符,在存取时就是利用运算符重载

void people::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {    // storing code
        //存数据
        ar << age << weight << height;
    }
    else
    {    // loading code
        //读数据
        ar >> age >> weight >> height;
    }
}

如果说类的属性中有自定义类型的数组,比如下面这种,其中CPoint是MFC类型对象

#pragma once
#include<afx.h>

class people :public CObject {
public:
    CArray<CPoint>m_point;
};

那么在 Serialize设置存取时可以安这样

void people::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {    // storing code
        //存数据
        ar << age << weight << height;
    }
    else
    {    // loading code
        //读数据
        ar >> age >> weight >> height;
    }
    /*直接使用数组调用该方法,因为数组已经实现了这个方法,数组存放的元素是CPoint,CPoint
      本省也是支持序列化*/
    m_point.Serialize(ar);
}

在程序启动时加载序列化

在Doc.cpp文件中找到序列化接口函数

void Cdraw3Doc::Serialize(CArchive& ar)
{
    if (ar.IsStoring())
    {
        // TODO: 在此添加存储代码
    }
    else
    {
        // TODO: 在此添加加载代码
    }
}

从view类里拿到要序列化的数据people*

void Cdraw3Doc::Serialize(CArchive& ar)
{
    //取出第一个view在链表中的位置
    POSITION pos = GetFirstViewPosition();
    //通过位置获得该view
    Cdraw3View* pView = (Cdraw3View* )GetNextView(pos);
    if (ar.IsStoring())
    {
        //存数据
        ar << pView->human;
    }
    else
    {
        //取数据
        ar >> pView->human;
    }
}

这样我们每次保存时数据就可以以二进制序列化保存,每次打开时又可以打开上次保存的内容

如果people*是一个数组的话,例如这样

那么我们在用序列化存取时就要先存取数组长度,再循环存取数组的内容

void Cdraw3Doc::Serialize(CArchive& ar)
{
    //取出第一个view在链表中的位置
    POSITION pos = GetFirstViewPosition();
    //通过位置获得该view
    Cdraw3View* pView = (Cdraw3View* )GetNextView(pos);
    //获得数组长度
    int cnt = pView->human.GetSize();
    if (ar.IsStoring())
    {
        //存数据
        ar << cnt;
        for (int i = 0; i < cnt; i++) {
            //循环存储数组
            ar << pView->human.GetAt(i);
        }
    }
    else
    {
        //取长度
        ar >> cnt;
        for (int i = 0; i < cnt; ++i) {
            //依次取数据,加入到数组中
            people* p;
            ar >> p;
            pView->human.Add(p);
        }

    }
}

到此这篇关于基于MFC实现类的序列化详解的文章就介绍到这了,更多相关MFC类的序列化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mfc文件操作CFile类之创建文件的方法

    mfc文件操作类CFile CFile类的几种构造函数 CFile();//不带参数的构造函数. CFile(int hFile);//带文件句柄参数的构造函数. CFile( LPCTSTR lpszFileName,//要打开的文件路径 UINT nOpenFlage //打开文件时的共享和访问模式 );//带文件路径和打开方式的构造函数 除了用构造函数打开文件外还可以用CFile类的成员函数Open来打开 OPen函数原型 virtual BOOL Open( LPCTSTR lpszFi

  • Visual C++中MFC消息的分类

    标准(窗口)消息:窗口消息一般与窗口内部运作有关,如创建窗口,绘制窗口,销毁窗口,通常,消息是从系统发到窗口,或从窗口发到系统.发送函数SendMessage()或者PostMessage().除WM_COMMAND之外,所有的以WM_开头的消息.从CWnd派生的类,都可以接受到这类消息.注意:标准消息并不需要我们指定处理函数名称,是默认的对应关系. 宏名称 对应消息 消息处理函数 ON_WM_CHAR WM_CHAR OnChar ON_WM_CLOSE WM_CLOSE OnClose ON

  • MFC扩展DLL中导出类和对话框的实现方法

    本文实例讲述了MFC扩展DLL中导出类和对话框的实现方法,分享给大家供大家参考.具体实现方法如下: 一般来说,如果要编写模块化的软件,就要对对动态链接库(DLL)有一定的了解,本人这段时间在修改以前的软件时,决定把重复用的类和对话框做到DLL中,下面就从一个简单的例子讲起,如何实现MFC扩展DLL中导出类和对话框. 程序运行结果如下图所示: 一.创建MFC扩展DLL 步骤: 运行Visual Studio 6.0->File->New...->Projects: 选择Mfc AppWiz

  • 基于MFC实现类的序列化详解

    序列化是将程序中的对象以一种二进制格式存储到存储设备中(例如文本/数据库等),以实现“永生”或随意“流动” 首先定义一个要序列化的类people,其属性有age.weight.height. #pragma once class people { public: int age; int weight; int height; }; 定义好后将该类添加到  项目名view.h  的类中,作为其属性,并且是指针类型 将需要存取的类实现序列化 1.序列化的类必须从CObject派生,或是从CObje

  • 基于visualvm监控类实现过程详解

    使用 visualvm干的第一件事情:监控类是否是多例模式 具体操作为: 1.首先启动本地项目,打开 jvisualvm,选择Tomcat(注意,在jdk目录下的名称里,命名前加了一个 j,别找不到了) 2.在[监视]栏,点击这个[堆Dump],就会监视此刻的堆内存状态 3.弹出了以下页面,选择[类]选项卡,根据类名排序,找到要看的类,这时我已经新建了一个实例 4.操作Web页面后,打开了对应的两个页面以后,再重复2-3步骤,会看到一个新的时刻的heapdump,发现实例数增加了2个,所以我这个

  • 基于java涉及父子类的异常详解

    java中的异常涉及到父子类的问题,可以归纳为一句话:子类的构造函数抛出的异常必须包含父类的异常,子类的方法可以选择抛出"范围小于等于"父类的异常或不抛出异常. 1. 为什么构造函数必须抛出包含父类的异常? 在<thingking in java>中有这么一段话: 异常限制:当覆盖方法时,只能抛出在基类方法的异常说明中列出的那些异常 异常限制对构造器不起作用,你会发现StormyInning的构造器可以抛出任何异常,而不必理会基类构造函数所抛出的异常.然而因为必须构造函数必

  • 基于java Files类和Paths类的用法(详解)

    Java7中文件IO发生了很大的变化,专门引入了很多新的类: import java.nio.file.DirectoryStream; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.

  • 基于NIO的Netty网络框架(详解)

    Netty是一个高性能.异步事件驱动的NIO框架,它提供了对TCP.UDP和文件传输的支持,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果. Netty的优点有: a.功能丰富,内置了多种数据编解码功能.支持多种网络协议. b.高性能,通过与其它主流NIO网络框架对比,它的综合性能最佳. c.可扩展性好,可通过它提供的ChannelHandler组件对网络通信方面进行灵活扩展. d.易用性,API使用简单.

  • Django框架之DRF 基于mixins来封装的视图详解

    基础视图 示例环境搭建:新建一个Django项目,连接Mysql数据库,配置路由.视图函数.序列化单独创建py文件 # 配置路由 from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^PublishView/', views.PublishView.as_vi

  • SpringBoot自定义Redis实现缓存序列化详解

    目录 1.自定义RedisTemplate 1.1.Redis API默认序列化机制 1.2.自定义RedisTemplate序列化机制 1.3.效果测试 2.自定义RedisCacheManager 2.1.Redis注解默认序列化机制 2.2.自定义RedisCacheManager 刚刚完成了Spring Boot整合Redis进行了数据的缓存管理,但缓存管理的实体类数据使用的是JDK序列化方式,不便于使用可视化管理工具进行查看和管理. 接下来分别针对基于注解的Redis缓存实现和基于AP

  • 基于java servlet过滤器和监听器(详解)

    1 过滤器 1.过滤器是什么? servlet规范当中定义的一种特殊的组件,用于拦截容器的调用. 注:容器收到请求之后,如果有过滤器,会先调用过滤器,然后在调用servlet. 2.如何写一个过滤器? 1.写一个java类,实现Filter接口; 2.在接口方法中实现拦截方法; 3.配置过滤器(web.xml); 3.配置初始化参数 1.配置初始化参数.(init-param) 2.通过filterconfig提供的getinitparamenter方法读取初始化的值. 4.优先级: 当有多个过

  • 基于ScheduledExecutorService的两种方法(详解)

    开发中,往往遇到另起线程执行其他代码的情况,用java定时任务接口ScheduledExecutorService来实现. ScheduledExecutorService是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响. 注意,只有当调度任务来的时候,ScheduledExecutorService才会真正启动一个线程,其余时间ScheduledExecutorService都是处于轮询任务的状态. 1.scheduleAtFix

  • 玩转JavaScript OOP - 类的实现详解

    概述 当我们在谈论面向对象编程时,我们在谈论什么? 我们首先谈论的是一些概念:对象.类.封装.继承.多态. 对象和类是面向对象的基础,封装.继承和多态是面向对象编程的三大特性. JavaScript提供了对象却缺乏类,它不能像C#一样能显式地定义一个类. 但是JavaScript的函数功能非常灵活,其中之一就是构造函数,结合构造函数和原型对象可以实现"类". 对象和类的概念 对象 "对象"是面向对象编程中非常重要的一个概念,一个对象是一个"东西"

随机推荐