c++ - Boost序列化子类

标签 c++ inheritance serialization boost boost-serialization

我有一个可序列化的基类 User :

class User
{
public:
    User();
    std::string GetLogin() const;
    void SetLogin(std::string login);

protected:
    std::string mLogin;
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & mLogin;

    }
};

这个类可以像这样被其他类继承:

class UserA : public User
{
    UserA();
private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<User>(*this);
        ar & mIsSomething;
    }
    bool mIsSomething = true;
}

为了处理这些用户,我有一个包含用户 vector 的“经理”类:

class Manager
{
public:

    bool Add(User user);
    bool Remove(unsigned int index);

private:
    std::vector<User> mUsers;

    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & mUsers;
    }
};

所以我的经理可能会被 UserA 或 UserB 填满(永远不会同时)。当我从 Manager 检索一个元素时,我只是将它转换回正确的子类。 这部分工作正常。

但是当我想序列化 Manager 类时,显然 Boost 不知道我正在尝试序列化哪种类型的 User 以及来自子类的额外字段未序列化。

我的解决方案是什么?
我的设计是否完全错误?
我应该将我的经理类(class)专门用于这样的事情吗?

class Manager
    {
        bool Add(UserA user);
        bool Add(UserB user);
    private:
        std::vector<UserA> mUsersA;
        std::vector<UserB> mUsersB;
}

最佳答案

So my manager can be filled with UserA , or UserB (never both at the same time)

不,它不能:

std::vector<User> mUsers;

门店 User按值的对象。参见 What is object slicing? .

想法

我还建议在具体用户类型上对管理器进行模板化,但看到您如何使用实际的类型层次结构,您似乎希望实际使用运行时多态性。

由于序列化多态类型比较复杂,让我给你看一个例子。

它还展示了如何使用例如boost::ptr_vector<>在动态存储对象的同时管理对象。

Live1 on Coliru

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/ptr_container/serialize_ptr_vector.hpp>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>

class User
{
public:
    User() {};
    virtual ~User() {}
    std::string GetLogin() const;
    void SetLogin(std::string login);

protected:
    std::string mLogin;
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /*version*/)
    {
        ar & mLogin;
    }
};

class UserA : public User
{
  public:
    UserA() {};
  private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /*version*/)
    {
        ar & boost::serialization::base_object<User>(*this);
        ar & mIsSomething;
    }
    bool mIsSomething = true;
};

class UserB : public User
{
  public:
    UserB() {};
  private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /*version*/)
    {
        ar & boost::serialization::base_object<User>(*this);
        ar & mIsSomethingElse;
    }
    bool mIsSomethingElse = true;
};

template <typename Tag>
class UserGen : public User
{
  public:
    UserGen() {};
  private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /*version*/)
    {
        ar & boost::serialization::base_object<User>(*this);
        ar & mIsGen;
    }
    bool mIsGen = true;
};

struct GenA;
struct GenB;
struct GenC;

BOOST_CLASS_EXPORT(User)
BOOST_CLASS_EXPORT(UserA)
BOOST_CLASS_EXPORT(UserB)
BOOST_CLASS_EXPORT(UserGen<GenA>)
BOOST_CLASS_EXPORT(UserGen<GenB>)
BOOST_CLASS_EXPORT(UserGen<GenC>)

#include <boost/type_index.hpp>

class Manager
{
public:

    template <typename User>
    bool Add(User const& user) {
        mUsers.push_back(new User(user));
        return true; // FIXME?
    }
    bool Remove(unsigned int index) {
        if (mUsers.size() > index) {
            mUsers.erase(mUsers.begin()+index);
            return true;
        }
        return false;
    }

    void dump() const {
        for (auto& u : mUsers) {
            std::cout << "user of type " << boost::typeindex::type_id_runtime(u) << "\n";
        }
    }

private:
    boost::ptr_vector<User> mUsers;

    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /*version*/)
    {
        ar & mUsers;
    }
};

#include <sstream>
#include <iostream>

int main() {
    std::stringstream ss;

    {
        Manager man;
        man.Add(UserA{});
        man.Add(UserB{});
        man.Add(UserGen<GenA>{});
        man.Add(UserGen<GenB>{});
        man.Add(UserGen<GenC>{});

        boost::archive::text_oarchive oa(ss);
        oa << man;
    }

    {
        boost::archive::text_iarchive ia(ss);
        Manager man;
        ia >> man;

        man.dump();
    }
}

打印

user of type UserA
user of type UserB
user of type UserGen<GenA>
user of type UserGen<GenB>
user of type UserGen<GenC>

1 链接 boost 1.59 在某种程度上失败了:( 谢谢@m.s。为了弄清楚 1.58 仍然有效

关于c++ - Boost序列化子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33365093/

相关文章:

C++ 重载转换运算符 hack

c++ - extern "C"在 C 中是否有任何影响?

asp.net - Azure appfabric 缓存、从 Linq 到 SQL 的匿名类的序列化问题

.net - 使用内联初始化反序列化 bool 数据成员时发生了奇怪的事情

c - 使用 C 进行架构上独立的数字序列化/反序列化

c++ - 可以在分配有新位置的指针上调用 delete 吗?

c++ - C++ 中的 T 类(您的定义)

Java 继承 : Overwritten or hidden methods

hibernate - JPA:是否可以更改继承层次结构中的 PK?

c++ - 防止使用重写的非虚函数 - 正确的方法?