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. linux 环境下bash脚本中找不到命令

    mr.sh: line 1: HADOOP_CMD: command not found mr.sh: line 4: INPUT_FILE_PATH: command not found mr.sh ...

  2. 七、docker基本命令

    Docker 基本命令 docker的基本命令 docker version :查看docker的版本号,包括客户端.服务端.依赖的Go等 [root@centos7 ~]# docker versi ...

  3. linux系统管理员 第五部分 1认识系统服务

    linux系统管理员 一 认识系统服务 二认识与分析登录文件 三启动流程.模组管理与loader 四网络设定与备份策略 五软件的安装  源代码与tarball 六软件的安装rpm   srpm与yum ...

  4. main()中的参数argc, argv

    转自:http://blog.csdn.net/eastmount/article/details/20413773 一.main()函数参数 通常我们在写主函数时都是void main()或int ...

  5. Android自制rom,为update.zip签名

    确认已经安装好openssl openssl genrsa -out key.pem openssl req -new -key key.pem -out request.pem openssl x5 ...

  6. Maven部署异常:on project standalone-pom: Cannot deploy artifact from the local repository解决方法

    MAVEN部署异常 org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache. ...

  7. sqlserver查询表大小

    IF OBJECT_ID('tempdb..#TB_TEMP_SPACE') IS NOT NULL DROP TABLE #TB_TEMP_SPACE GO CREATE TABLE #TB_TEM ...

  8. Repeat Array Generator & String.repeat

    Repeat Array Generator RepeatArrayGenerator "use strict"; /** * * @author xgqfrms * @licen ...

  9. BZOJ 1861 [Zjoi2006]Book 书架 ——Splay

    [题目分析] 模板题目. 首尾两个虚拟结点,十分方便操作. [代码] #include <cstdio> #include <cstring> #include <cma ...

  10. SPOJ 375 Query on a tree【树链剖分】

    题目大意:给你一棵树,有两个操作1.修改一条边的值,2.询问从x到y路径上边的最大值 思路:如果树退化成一条链的话线段树就很明显了,然后这题就是套了个树连剖分,调了很久终于调出来第一个模板了 #inc ...