boost::serialization 也支持c++的多态,这样我们就能够通过使用基类的指针来转存派生类,

我们接着上一篇(

boost::serialization(2)序列化基类

)的样例来看:

基类和派生类的代码例如以下:

class student_info
{
public:
student_info() {}
virtual ~student_info() {}
student_info(const std::string& sn, const std::string& snm, const std::string& sg)
: name_(sn), number_(snm), grade_(sg)
{
} virtual void print_info() const
{
std::cout << name_ << " " << number_ << " " << grade_ << std::endl;
} private:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(name_);
ar & BOOST_SERIALIZATION_NVP(number_);
ar & BOOST_SERIALIZATION_NVP(grade_);
} private:
std::string name_;
std::string number_;
std::string grade_;
}; class middle_student : public student_info
{
public:
middle_student() {}
virtual ~middle_student() {}
middle_student(const std::string& sn, const std::string& snm, const std::string& sg, int age)
: student_info(sn, snm, sg), age_(age)
{ } virtual void print_info()
{
student_info::print_info();
std::cout << age_ << std::endl;
} private:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & boost::serialization::base_object<student_info>(*this);
ar & BOOST_SERIALIZATION_NVP(age_);
} private:
int age_;
};

在派生类中使用了基类的基类的序列化: ar & boost::serialization::base_object<student_info>(*this);

以下我们来看怎么使用基类的指针转存派生类:

save的代码:

void save()
{
std::ofstream ofs("t7.xml");
boost::archive::xml_oarchive oa(ofs);
student_info* sdinfo = new middle_student("wyp", "0099", "1", 15);//#1
oa << BOOST_SERIALIZATION_NVP(sdinfo);//#2
std::cout << "xxxx" << std::endl;
delete sdinfo;
}

#1:用一个基类的指针指向了一个用new申请的派生类的指针,非常easy,都知道这就是c++的多态。

#2:这个代码和曾经的一样,还是用一个宏来包装指针。

load的代码:

void load()
{
std::ifstream ifs("t7.xml");
boost::archive::xml_iarchive ia(ifs);
student_info* sdinfo = NULL;//#1
ia >> BOOST_SERIALIZATION_NVP(sdinfo);//#2
middle_student* mds = dynamic_cast<middle_student*>(sdinfo);//#3
mds->print_info();
}

#1:基类的指针

#2:load的时候也须要宏来包装

#3:这个大家都熟悉

測试代码:

void fun()
{
save();
load();
}

编译执行!。

。。。

。。

结果抛出异常:boost::archive::archive_exception at memory location 0x0017eb30...

google了一下,以下链接给出了一个解决方法

http://stackoverflow.com/questions/1332602/how-to-serialize-derived-template-classes-with-boost-serialize

大概分为3个步骤:

步骤1:BOOST_SERIALIZATION_ASSUME_ABSTRACT(className),用这个宏来告诉boost className是一个抽象类

步骤2:在save操作中注冊派生类:oa.template register_type<middle_student>(NULL),

       一定要在oa << BOOST_SERIALIZATION_NVP(sdinfo)之前注冊。

步骤3:在load操作中注冊派生了:ia.template register_type<middle_student>(NULL)

       一定要在ia >> BOOST_SERIALIZATION_NVP(sdinfo)之前注冊。

改动后的代码例如以下:

void save()
{
std::ofstream ofs("t7.xml");
boost::archive::xml_oarchive oa(ofs);
oa.template register_type<middle_student>(NULL);
student_info* sdinfo = new middle_student("wyp", "0099", "1", 15);
oa << BOOST_SERIALIZATION_NVP(sdinfo);
delete sdinfo;
} void load()
{
std::ifstream ifs("t7.xml");
boost::archive::xml_iarchive ia(ifs);
ia.template register_type<middle_student>(NULL);
student_info* sdinfo = NULL;
ia >> BOOST_SERIALIZATION_NVP(sdinfo);
middle_student* mds = dynamic_cast<middle_student*>(sdinfo);
mds->print_info();
}

好这下应改没有异常了吧。

结果编译就出错了!



错误在这个函数里面

 // Anything not an attribute and not a name-value pair is an
// error and should be trapped here.
template<class T>
void save_override(T & t, BOOST_PFTO int)
{
// If your program fails to compile here, its most likely due to
// not specifying an nvp wrapper around the variable to
// be serialized.
BOOST_MPL_ASSERT((serialization::is_wrapper< T >));
this->detail_common_oarchive::save_override(t, 0);
}

看凝视就知道了,序列化时存在有些数据没有包装,就是没实用那个宏。

就细致看一下序列化的代码发现这段代码中有一个没用宏来包装:

private:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & boost::serialization::base_object<student_info>(*this);//here!!!!!!!!!!!
ar & BOOST_SERIALIZATION_NVP(age_);
}

在调用基类的序列化时没用宏包装

改动例如以下:

private:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
//ar & boost::serialization::base_object<student_info>(*this);
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(student_info);
ar & BOOST_SERIALIZATION_NVP(age_);
}

编译执行ok!

执行结果例如以下 t7.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?

>

<!DOCTYPE boost_serialization>

<boost_serialization signature="serialization::archive" version="10">

<sdinfo class_id="0" tracking_level="1" version="0" object_id="_0">

<student_info class_id="1" tracking_level="1" version="0" object_id="_1">

<name_>wyp</name_>

<number_>0099</number_>

<grade_>1</grade_>

</student_info>

<age_>15</age_>

</sdinfo>

</boost_serialization>

完整代码例如以下

#include <fstream>
#include <iostream>
#include <algorithm>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/base_object.hpp> class student_info
{
public:
student_info() {}
virtual ~student_info() {}
student_info(const std::string& sn, const std::string& snm, const std::string& sg)
: name_(sn), number_(snm), grade_(sg)
{
} virtual void print_info() const
{
std::cout << name_ << " " << number_ << " " << grade_ << std::endl;
} private:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(name_);
ar & BOOST_SERIALIZATION_NVP(number_);
ar & BOOST_SERIALIZATION_NVP(grade_);
} private:
std::string name_;
std::string number_;
std::string grade_;
}; BOOST_SERIALIZATION_ASSUME_ABSTRACT(student_info) class middle_student : public student_info
{
public:
middle_student() {}
virtual ~middle_student() {}
middle_student(const std::string& sn, const std::string& snm, const std::string& sg, int age)
: student_info(sn, snm, sg), age_(age)
{ } virtual void print_info()
{
student_info::print_info();
std::cout << age_ << std::endl;
} private:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(student_info);
ar & BOOST_SERIALIZATION_NVP(age_);
} private:
int age_;
}; void save()
{
std::ofstream ofs("t7.xml");
boost::archive::xml_oarchive oa(ofs);
oa.template register_type<middle_student>(NULL);
student_info* sdinfo = new middle_student("wyp", "0099", "1", 15);
oa << BOOST_SERIALIZATION_NVP(sdinfo);
delete sdinfo;
} void load()
{
std::ifstream ifs("t7.xml");
boost::archive::xml_iarchive ia(ifs);
ia.template register_type<middle_student>(NULL);
student_info* sdinfo = NULL;
ia >> BOOST_SERIALIZATION_NVP(sdinfo);
middle_student* mds = dynamic_cast<middle_student*>(sdinfo);
mds->print_info();
} void fun()
{
save();
load();
}

boost::serialization 用基类指针转存派生类(错误多多,一波三折)的更多相关文章

  1. C++_派生类的构造函数及派生类和基类之间的特殊关系

    派生类和基类的概念及派生类构造函数的原理: 创建一个叫做TableTennisPlayer的基类,记录会员的名字和是否有球桌. //声明一个基类 class TableTennisPlayer { p ...

  2. 空类指针为什么可以调用类的成员函数 以及 A(){}和A();

    1. 代码及问题 #include <iostream> using namespace std; class A { public: A() {} //A *p = new A()时:此 ...

  3. C++类继承--基类new和用派生类new的区别

    实际上无论是用基类还是派生类New, 结果是一样的: #include <stdio.h> class Base { public: int a; Base(){ a=0; } virtu ...

  4. 基类的两个派生类再派生一个派生类 用virtual避免二义性

    class vehicle{ int MaxSpeed; int Weight;public: vehicle(int maxspeed, int weight) :MaxSpeed(maxspeed ...

  5. 虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?

    五条基本规则: 1.如果基类已经插入了vptr, 则派生类将继承和重用该vptr.vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的 ...

  6. C++基类和派生类之间的转换

    本文讲解内容的前提是派生类继承基类的方式是公有继承,关键字public 以下程序为讲解用例. #include<iostream> using namespace std; class A ...

  7. OOP1(定义基类和派生类)

    面向对象程序设计基于三个基本概念:数据抽象,继承和动态绑定 数据抽象是一种依赖于接口和实现分离的编程技术.继承和动态绑定对程序的编号有两方面的影响:一是我们可以更容易地定义与其它类相似但不完全相同的类 ...

  8. C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构

    一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...

  9. 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)

    [源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...

随机推荐

  1. unittest编写Web测试用例

    案例:百度搜索关键词:“unittest” test_baidu.py: from selenium import webdriver from time import sleep import un ...

  2. CoCoS 2D-JS的开发环境搭建

    CoCoS 2D-JS的开发环境搭建 在Hbuilder中新建web项目,将cocos2d-js-v3.9.js复制到在js文件夹下,将project.json复制到工程的根目录下 在index.ht ...

  3. php.ini配置参数详解

    下面对php.ini中一些安全相关参数的配置进行说明 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 ...

  4. 30分钟学会如何使用Shiro(转自:http://www.cnblogs.com/learnhow/p/5694876.html)

    本篇内容大多总结自张开涛的<跟我学Shiro>原文地址:http://jinnianshilongnian.iteye.com/blog/2018936 我并没有全部看完,只是选择了一部分 ...

  5. hdu6061[NTT推公式] 2017多校3

    /*hdu6061[NTT推公式] 2017多校3*/ #include <bits/stdc++.h> using namespace std; typedef long long LL ...

  6. 【Luogu】P1119灾后重建(Floyd)

    题目链接 见题解: feilongz. 这里只放代码. #include<cstdio> #include<cstring> #include<cstdlib> # ...

  7. P1026 统计单词个数 (动态规划)

    题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单 ...

  8. scrapy介绍及源码分析

    一 简介 Scrapy基于事件驱动网络框架 Twisted 编写.因此,Scrapy基于并发性考虑由非阻塞(即异步)的实现. 官方文档 :https://docs.scrapy.org/en/late ...

  9. Powerdesigner 使用小技巧

    1.table与table之间:改直角为直线; 2.Name 和code 不联动

  10. Unity3D游戏开发之C#编程中常见数据结构的比较

    一.前言 Unity3D是如今最火爆的游戏开发引擎,它可以让我们能轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型的互动内容.它支持2D/3D游戏开发,据不完全统计,目前国内80%的手机游戏都 ...