事件类序列化

Event class serialization

本文关键字:序列化 事件      更新时间:2023-10-16

您好,我正在检查C++中的各种对象序列化方法,但找不到合适的解决方案。我现在正在检查的是使用宏来序列化各种类。代码可以编译,但是当函数 serialize_example(); 调用Event* newEvent = dynamic_cast<Event*>(Persistent::load(stream));时,我0xC0000005: Access violation reading location 0xCCCCCCC8.

Persistent * obj = dynamic_cast<Persistent *>(clone);调用中发生异常。任何人都可以帮我解决这个问题吗?这是代码:

void serialize_example()
{
auto_ptr<Event> event(new Event());
fstream file("try.data",
    ios::out | ios::in | ios::binary | ios::trunc);
ArchiveFile stream(&file);
if (!file)
    throw "Unable to open file for writing";
event->store(stream);
file.seekg(0, ios::beg);
Event* newEvent = dynamic_cast<Event*>(Persistent::load(stream));
event.reset(newEvent);
file.close();
}

事件.h

#pragma once
#include "Persist.h"
#define PERSISTENT_DECL(className) 
public: 
 virtual Clonable* createObj()  
{ 
return new className(); 
} 
 private: 
static AddClonable _addClonable; 
#define PERSISTENT_IMPL(className) 
AddClonable className::_addClonable(#className, new className());
class Event : public Persistent {
private:
 int _id;
public:
Event() : _id(0) {}
virtual ~Event() {}
int getId()  { return _id; }
protected:
virtual void serialize(Archive& stream)
{
    if (stream.isStoring())
        stream << _id;
    else
        stream >> _id;
}
PERSISTENT_DECL(Event)
};
 PERSISTENT_IMPL(Event)

坚持.cpp

#include "Persist.h"
#include <vector>
#include <iostream>
using namespace std;
Archive& Archive::operator<<(int val)
{
write(&val, sizeof(int));
return *this;
}
Archive& Archive::operator>>(int& val)
{
read(&val, sizeof(int));
return *this;
}
Archive& Archive::operator<<(const string& str)
{
int length = str.length();
*this << length;
write(str.c_str(), sizeof(char) * length);
return *this;
}
Archive& Archive::operator>>(string& str)
{
int length = -1;
*this >> length;
vector<char> mem(length + 1);
char* pChars = &mem[0];
read(pChars, sizeof(char) * length);
mem[length] = NULL;
str = pChars;
return *this;
}
void ArchiveFile::write(const void* buffer, size_t length)
{
_stream->write((const char*)buffer, length);
if (!*_stream)
    throw "ArchiveFile::write Error";
}
void ArchiveFile::read(void* buffer, size_t length)
{
_stream->read((char*)buffer, length);
if (!*_stream)
    throw "ArchiveFile::read Error";
}
void Persistent::store(Archive& stream) const
{
string className = typeid(*this).name();
className = className.substr(className.find(' ') + 1);
stream << className;
int ver = version();
stream << ver;
stream.setDirection(true);
const_cast<Persistent *>(this)->serialize(stream);
}
Persistent* Persistent::load(Archive& stream)
{
string className;
stream >> className;
Clonable* clone = Clonables::Instance().create(className.c_str());
if (clone == NULL)
    throw "Persistent::load : Error creating object";
auto_ptr<Clonable> delitor(clone);
Persistent * obj = dynamic_cast<Persistent *>(clone);
if (obj == NULL) {
    throw "Persistent::load : Error creating object";
}
int ver = -1;
stream >> ver;
if (ver != obj->version())
    throw "Persistent::load : unmatched version number";
stream.setDirection(false);
obj->serialize(stream);
delitor.release();
return obj;
}

动态.h

#pragma once
#include <string>
using namespace std;
#include <map>

 class Clonable
{
public:
virtual ~Clonable() {}
virtual Clonable* createObj()  = 0;
};

class Clonables {
private:
typedef map<string, const Clonable*> NameToClonable;
NameToClonable __clonables;
private:
Clonables() {}
Clonables(const Clonables&);                 // Prevent copy-construction
Clonables& operator=(const Clonables&);      //  Prevent assignment
~Clonables()
{
    for (NameToClonable::const_iterator it = __clonables.begin(); it !=       __clonables.end(); it++) {
        const Clonable* clone = it->second;
        delete clone;
    }
    __clonables.clear();
}
public:
static Clonables& Instance()
{
    static Clonables instance;   // Guaranteed to be destroyed.                              
    return instance;    // Instantiated on first use.
}
public:
void addClonable(const char* className, const Clonable* clone)
{
    string name = className;
    NameToClonable::const_iterator it = __clonables.find(name);
    if (it == __clonables.end()) {
        __clonables[name] = clone;
    }
}
Clonable* create(const char *className)
{
    string name = className;
    NameToClonable::const_iterator it = __clonables.find(name);
    if (it == __clonables.end()) return NULL;
    const Clonable* clone = it->second;
}
};
class AddClonable {
public:
AddClonable(const char* className, const Clonable* clone) {
    Clonables::Instance().addClonable(className, clone);
}
};

您可以使用 Boost.Serialization 作为示例。我想在这里举一个例子。您可以轻松序列化对象重载和运算符。

#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
struct plane {
    std::string id;
    std::string name;
    int x;
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & id;
        ar & name;
        ar & x;
    }
};
int serialization()
{
    {
        plane old_plane;
        old_plane.id = "12345";
        old_plane.id = "plane foo";
        old_plane.x = 12345;
        // boost::archive::text_oarchive oa(ofs);
        std::ofstream ofs("filename");
        boost::archive::binary_oarchive oa(ofs);
        oa << old_plane;
    }
    ///////////////////////////////////////////////////////////////
    plane new_plane;
    std::ifstream ifs("filename");
    //boost::archive::text_iarchive ia(ifs);
    boost::archive::binary_iarchive ia(ifs);
    ia >> new_plane;
    ///////////////////////////////////////////////////////////////
    std::cout << new_plane.id << " ";
    std::cout << new_plane.name << " ";
    std::cout << new_plane.x << std::endl;

    return 0;
}