boost::serialization 用基类指针转存派生类(错误多多,一波三折)
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 用基类指针转存派生类(错误多多,一波三折)的更多相关文章
- C++_派生类的构造函数及派生类和基类之间的特殊关系
派生类和基类的概念及派生类构造函数的原理: 创建一个叫做TableTennisPlayer的基类,记录会员的名字和是否有球桌. //声明一个基类 class TableTennisPlayer { p ...
- 空类指针为什么可以调用类的成员函数 以及 A(){}和A();
1. 代码及问题 #include <iostream> using namespace std; class A { public: A() {} //A *p = new A()时:此 ...
- C++类继承--基类new和用派生类new的区别
实际上无论是用基类还是派生类New, 结果是一样的: #include <stdio.h> class Base { public: int a; Base(){ a=0; } virtu ...
- 基类的两个派生类再派生一个派生类 用virtual避免二义性
class vehicle{ int MaxSpeed; int Weight;public: vehicle(int maxspeed, int weight) :MaxSpeed(maxspeed ...
- 虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?
五条基本规则: 1.如果基类已经插入了vptr, 则派生类将继承和重用该vptr.vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的 ...
- C++基类和派生类之间的转换
本文讲解内容的前提是派生类继承基类的方式是公有继承,关键字public 以下程序为讲解用例. #include<iostream> using namespace std; class A ...
- OOP1(定义基类和派生类)
面向对象程序设计基于三个基本概念:数据抽象,继承和动态绑定 数据抽象是一种依赖于接口和实现分离的编程技术.继承和动态绑定对程序的编号有两方面的影响:一是我们可以更容易地定义与其它类相似但不完全相同的类 ...
- C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构
一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...
- 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)
[源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...
随机推荐
- unittest编写Web测试用例
案例:百度搜索关键词:“unittest” test_baidu.py: from selenium import webdriver from time import sleep import un ...
- CoCoS 2D-JS的开发环境搭建
CoCoS 2D-JS的开发环境搭建 在Hbuilder中新建web项目,将cocos2d-js-v3.9.js复制到在js文件夹下,将project.json复制到工程的根目录下 在index.ht ...
- 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 ...
- 30分钟学会如何使用Shiro(转自:http://www.cnblogs.com/learnhow/p/5694876.html)
本篇内容大多总结自张开涛的<跟我学Shiro>原文地址:http://jinnianshilongnian.iteye.com/blog/2018936 我并没有全部看完,只是选择了一部分 ...
- hdu6061[NTT推公式] 2017多校3
/*hdu6061[NTT推公式] 2017多校3*/ #include <bits/stdc++.h> using namespace std; typedef long long LL ...
- 【Luogu】P1119灾后重建(Floyd)
题目链接 见题解: feilongz. 这里只放代码. #include<cstdio> #include<cstring> #include<cstdlib> # ...
- P1026 统计单词个数 (动态规划)
题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份(1<k<=40),且每份中包含的单 ...
- scrapy介绍及源码分析
一 简介 Scrapy基于事件驱动网络框架 Twisted 编写.因此,Scrapy基于并发性考虑由非阻塞(即异步)的实现. 官方文档 :https://docs.scrapy.org/en/late ...
- Powerdesigner 使用小技巧
1.table与table之间:改直角为直线; 2.Name 和code 不联动
- Unity3D游戏开发之C#编程中常见数据结构的比较
一.前言 Unity3D是如今最火爆的游戏开发引擎,它可以让我们能轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型的互动内容.它支持2D/3D游戏开发,据不完全统计,目前国内80%的手机游戏都 ...