【问题标题】:Not able to serialize data properly using boost无法使用 boost 正确序列化数据
【发布时间】:2020-01-15 02:09:39
【问题描述】:

我对序列化非常陌生,我正在尝试使用 boost 来序列化我的数据。

这是我打算做的虚拟代码。

我正在使用 Geometry 类作为其他类(如 Sphere 、 Rectangle 等)的接口。

我遇到的问题是这一行“c_Restored->PrintContainer();”应该调用Sphere类的Virtual打印函数,但它调用的是Sphere类的Parent Geometry类打印函数。

#include "pch.h"
#include <iostream>
#include<fstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include "Container.h"
#include "Geometry.h"
#include "Sphere.h"

int main()
{
    const char* fileName = "saved.txt";
    Geometry* gg = new Sphere;
    Container *c = new Container("My Container", gg); // I have created a sphere object
    // save data
    {
        // Create an output archive
        std::ofstream ofs(fileName);
        boost::archive::text_oarchive ar(ofs);
        ar & c ;            
    }
    Container* c_Restored;  
    //load data
    {
        // create an input stream
        std::ifstream ifs(fileName);
        boost::archive::text_iarchive ar(ifs);
        ar & c_Restored;
    }

    Sphere* g1 = (Sphere*)c_Restored->getGeomtry();
    c_Restored->PrintContainer();
    g1->PrintGeom();  // This should call the Sphere PrintGeom function ???
    do
    {
        std::cout << '\n' << "Press a key to continue...";
    } while (std::cin.get() != '\n');
}

这是容器类。

#pragma once

#include <boost/serialization/base_object.hpp>
#include <boost/serialization/split_member.hpp>
#include "Geometry.h"
class Container
{
private:
    std::string stdstrCont;
    Geometry* geom;

public:
    Container() : stdstrCont() { geom = new Geometry; }

    
    Container( std::string str , Geometry* geometry) : stdstrCont(str )
{ 
    Sphere* sph = new Sphere;
    geom = new Sphere(*sph);
}


    ~Container()
    {
        if (geom != nullptr)
            delete geom;
    }

    Geometry* getGeomtry()
    {
        return geom;
    }

    void PrintContainer()
    {
        std::cout << stdstrCont;
    }

private:

    friend class boost::serialization::access;

    void serialize(Archive& ar, const unsigned version) {
    Sphere* sss = (Sphere*)geom;
    ar & stdstrCont & sss;
}
    
};

这是几何类

#pragma once

#include <string>

class Geometry
{
private:
    std::string stdstringGeom;

public:
     virtual void  PrintGeom()
    {
        std::cout << "geometry virtual function";
    }

private:
        
    friend class boost::serialization::access;


    template <typename Archive>
    void serialize(Archive& ar, const unsigned version) {
        ar & stdstringGeom;
    }
};

这是球类。

包括“Geometry.h”

class Sphere : public Geometry
{
private:
    std::string stdstrSphere;


public:
    Sphere() : stdstrSphere( "DefaultSphere"){}
    Sphere( std::string str) : stdstrSphere(str) {}
    void PrintGeom()
    {
        std::cout << "Sphere Virtual Function" << std::endl;
    }

private:
    typedef Geometry _Super;
    friend class boost::serialization::access;


    template <typename Archive>
    void serialize(Archive& ar, const unsigned version) {
        ar & boost::serialization::base_object<_Super>(*this);
        ar & stdstrSphere;
    }

};

我觉得问题出在容器序列化函数中。

 template <typename Archive>
        void serialize(Archive& ar, const unsigned version) {
            
            ar & stdstrCont & geom;
        }

虽然我正在序列化一个 Sphere 对象,但在反序列化它时构造了一个 Geomtry 对象。

【问题讨论】:

  • 至少部分问题在于Container ctor 中的声明 *geom = *geometry;slicing Sphere 作为参数传递。还是我错过了重点?
  • @G.M 是的,它正在切片,但是当我尝试这样做时 -> Sphere* sph = new Sphere; geom = new Sphere(*sph);
  • Container( std::string str , Geometry* geometry) 这个构造函数没有任何意义。您想在这里实现什么目标?
  • 在调用c_Restored-&gt;getGeomtry(); 之前,分配给Container* c_Restored; 的内存在哪里?在查看 boost 示例时,我没有注意到任何关于为指针变量分配内存的内容。在使用调试器单步执行代码时,您是否观察到,代码执行实际上会通过您的序列化过程?

标签: c++ c++11 serialization boost


【解决方案1】:

@G.M.就在他的cmets里。

在这里,您将Sphere 对象分割成Geometry 对象:

    Container* c = new Container("My Container", new Sphere());
...

    Container(std::string str, Geometry* geometry) : stdstrCont(str)
    {
        geom = new Geometry;
        *geom = *geometry;
    }

一旦切片完成,它一个Geometry 对象,然后正确的序列化是将其序列化(并恢复)为基础Geometry 对象。所以我相当确定 boost 序列化可以正常工作,但是你只是在给它喂垃圾(或者至少不是你打算喂它的东西)。

事实上,您的main 的这个非常简化的版本还在Geometry 类中调用printGeom(切片后应该如此):

int main()
{
    Container* c = new Container("My Container", new Sphere);
    Sphere* g1 = (Sphere*)c->getGeomtry();
    g1->PrintGeom();
}

所以我的建议是修复你的Container 构造函数(这取决于你想要什么,可能涉及在Sphere 中创建一个复制构造函数)。如果这会导致新问题,请在此处专门针对该部分写一个新问题。

【讨论】:

  • 请查看容器构造函数和序列化函数的更新代码,现在切片不应该发生,但我仍然得到几何虚拟函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-16
  • 2022-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多