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. ZOJ 3469 区间DP Food Delivery

    题解 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm ...

  2. Java-确定被加载类的路径

    如何输出当前类在硬盘的物理路径 package com.tj; import java.net.URL; import java.security.CodeSource; import java.se ...

  3. 2017 ACM/ICPC Asia Regional Shenyang Online

    cable cable cable Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  4. 安卓ImageView.src设置图片拉伸、填满控件的方法

    代码改变世界 安卓ImageView.src设置图片拉伸.填满控件的方法 需要给你的ImageView布局加上Android:adjustViewBounds="true"

  5. [luoguP2221] [HAOI2012]高速公路(线段树)

    传送门 考虑每一段对答案的贡献 用每一段的左端点来表示当前这一段,那么区间就变成了[1,n-1] 如果询问区间[l,r],其中一个点的位置为x,则它对答案的贡献为(x-l)*(r-x)*s[x](s[ ...

  6. [BZOJ1582] [Usaco2009 Hol]Holiday Painting 节日画画(线段树)

    传送门 线段树区间修改傻题 #include <cstdio> #include <cstring> #include <iostream> #define N 5 ...

  7. 2013 Asia acm Hangzhou Regional Contest 杭州现场赛

     B Stealing Harry Potter's Precious 题目大意:给定一个n*m的地图,某些点可以走,某些点可以走某些点不可以走,给定一个起点,又给出了k个点k<=4,要求从起点 ...

  8. bzoj2144 跳跳棋 二分

    [bzoj2144]跳跳棋 Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位 ...

  9. JQuery Mobile 的引用代码,以及在手机浏览器上字体太小的解决办法

    JQuery Mobile 的引用代码: <link rel="stylesheet" href="http://code.jquery.com/mobile/1. ...

  10. ThinkPHP5.1入门

    ThinkPHP5.1入门 ===================================Composer的官方网站:https://www.phpcomposer.com/========= ...