升压连载子类 [英] Boost serialize child class

查看:102
本文介绍了升压连载子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有基类用户是序列化的:

 类用户
{
上市:
    用户();
    标准::字符串GetLogin()const的;
    无效SetLogin(标准::字符串登录);保护:
    标准::字符串mLogin;
    友元类的boost ::系列化::访问;    模板<类归档和GT;
    无效连载(归档和放大器; AR,const的无符号整型版)
    {
        AR&安培; mLogin;    }
};

这类可以通过其他类继承这样的:

 类用户A:公共用户
{
    用户A();
私人的:
    友元类的boost ::系列化::访问;    模板<类归档和GT;
    无效连载(归档和放大器; AR,const的无符号整型版)
    {
        AR&安培;提高::系列化:: base_object<使用者>(*此);
        AR&安培; mIsSomething;
    }
    布尔mIsSomething = TRUE;
}

要处理这些用户,我有一个经理类,它包含一个用户向量:

 类经理
{
上市:    布尔添加(用户用户);
    布尔删除(无符号整数指数);私人的:
    的std ::矢量<使用者名称> mUsers;    友元类的boost ::系列化::访问;    模板<类归档和GT;
    无效连载(归档和放大器; AR,const的无符号整型版)
    {
        AR&安培; mUsers;
    }
};

所以,我的经理可以填充用户A或用户B(永远都在同一时间)。当我检索管理​​器中的元素我只是将它转换回正确的子类。
这部分工作正常。

但是,当我想序列化管理​​类明显提升不知道哪一种用户我'的米试图序列化和从子类中的附加字段不序列化。

什么这里是我的解决方案?结果
请问我的设计是完全地错了?结果
我应该专注我的经理类这样的事情?

 类经理
    {
        布尔加入(用户A用户);
        布尔加入(用户B用户);
    私人的:
        的std ::矢量<&用户A GT; mUsersA;
        的std ::矢量<用户B> mUsersB;
}


解决方案

  

所以,我的经理可以填充用户A或用户B(永远都在同一时间)


没有它不能

 的std ::矢量<使用者名称> mUsers;

商店用户通过值对象。请参见什么是对象切片?

的思考

我还建议模板化的具体用户类型的经理,但看到你如何使用一个实际的类型层次,看来你可能会寻找到实际使用的运行时多态性。

由于序列多态类型是稍微复杂,让我告诉你一个样本。

这也说明了如何使用例如的boost :: ptr_vector<方式> ,同时动态地保持他们管理的对象

<大骨节病> 1 上Coliru

 的#include&LT;升压/存档/ text_iarchive.hpp&GT;
#包括LT&;升压/存档/ text_oarchive.hpp&GT;#包括LT&;升压/ ptr_container / ptr_vector.hpp&GT;
#包括LT&;升压/ ptr_container / serialize_ptr_vector.hpp&GT;#包括LT&;升压/系列化/ serialization.hpp&GT;
#包括LT&;升压/系列化/ access.hpp&GT;
#包括LT&;升压/系列化/ base_object.hpp&GT;
#包括LT&;升压/系列化/ export.hpp&GT;
#包括LT&;升压/系列化/ string.hpp&GT;
#包括LT&;升压/系列化/ vector.hpp&GT;类用户
{
上市:
    用户(){};
    虚拟〜用户(){}
    标准::字符串GetLogin()const的;
    无效SetLogin(标准::字符串登录);保护:
    标准::字符串mLogin;
    友元类的boost ::系列化::访问;    模板&LT;类归档和GT;
    无效连载(归档和放大器; AR,const的无符号整型/ *版* /)
    {
        AR&安培; mLogin;
    }
};用户A类:公共用户
{
  上市:
    用户A(){};
  私人的:
    友元类的boost ::系列化::访问;    模板&LT;类归档和GT;
    无效连载(归档和放大器; AR,const的无符号整型/ *版* /)
    {
        AR&安培;提高::系列化:: base_object&lt;使用者&GT;(*此);
        AR&安培; mIsSomething;
    }
    布尔mIsSomething = TRUE;
};类用户B:公共用户
{
  上市:
    用户B(){};
  私人的:
    友元类的boost ::系列化::访问;    模板&LT;类归档和GT;
    无效连载(归档和放大器; AR,const的无符号整型/ *版* /)
    {
        AR&安培;提高::系列化:: base_object&lt;使用者&GT;(*此);
        AR&安培; mIsSomethingElse;
    }
    布尔mIsSomethingElse = TRUE;
};模板&LT; typename的标签&GT;
类UserGen:公共用户
{
  上市:
    UserGen(){};
  私人的:
    友元类的boost ::系列化::访问;    模板&LT;类归档和GT;
    无效连载(归档和放大器; AR,const的无符号整型/ *版* /)
    {
        AR&安培;提高::系列化:: base_object&lt;使用者&GT;(*此);
        AR&安培; mIsGen;
    }
    布尔mIsGen =真;
};结构吉纳;
结构GENB;
结构GENC;BOOST_CLASS_EXPORT(用户)
BOOST_CLASS_EXPORT(用户A)
BOOST_CLASS_EXPORT(用户B)
BOOST_CLASS_EXPORT(UserGen&LT;&吉纳GT;)
BOOST_CLASS_EXPORT(UserGen&LT;&GENB GT;)
BOOST_CLASS_EXPORT(UserGen&LT;&GENC GT;)#包括LT&;升压/ type_index.hpp&GT;一流的管理
{
上市:    模板&LT; typename的使用者名称&gt;
    布尔添加(用户常量和放大器;用户){
        mUsers.push_back(新用户());
        返回true; // 整我?
    }
    布尔删除(无符号整数指数){
        如果(mUsers.size()&GT;指数){
            mUsers.erase(mUsers.begin()+指数);
            返回true;
        }
        返回false;
    }    无效转储()const的{
        为(自动&安培; U:mUsers){
            性病::法院LT&;&LT; &LT类型的用户;&LT;提高:: typeindex :: type_id_runtime(U)&LT;&LT; \\ n;
        }
    }私人的:
    提高:: ptr_vector&lt;使用者&GT; mUsers;    友元类的boost ::系列化::访问;    模板&LT;类归档和GT;
    无效连载(归档和放大器; AR,const的无符号整型/ *版* /)
    {
        AR&安培; mUsers;
    }
};#包括LT&;&sstream GT;
#包括LT&;&iostream的GT;诠释主(){
    的std :: stringstream的SS;    {
        经理人;
        man.Add(用户A {});
        man.Add(用户B {});
        man.Add(UserGen&LT;&吉纳GT; {});
        man.Add(UserGen&所述; GENB&GT; {});
        man.Add(UserGen&所述; GENC&GT; {});        提高::档案:: text_oarchive的OA(SS);
        OA&LT;&LT;人;
    }    {
        提高::档案:: text_iarchive IA(SS);
        经理人;
        IA&GT;&GT;人;        man.dump();
    }
}

打印

 类型用户A的用户
类型用户B的用户
吉纳&GT;类型UserGen&LT的用户;
GENB&GT;类型UserGen&LT的用户;
GENC&GT;类型UserGen&LT的用户;


1 连接升压1.59不知何故未能有:(
感谢@ M.S。搞清楚1.58仍然有效。

I have base class User which is serializable :

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;

    }
};

This class can be inherited by other class like this :

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;
}

To handle those user i have a "manager" class which contain a User 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;
    }
};

So my manager can be filled with UserA , or UserB (never both at the same time). When i retrieve an element from Manager i simply cast it back to the correct child class. This part is working fine.

But when i want to serialize the Manager class obviously Boost don't know which kind of User i'm trying to serialize and the extra fields from the child class are not serialized.

What are my solution here ?
Does my design is completly wrong ?
Should i specialize my manager class to something like this ?

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)

No it can't:

std::vector<User> mUsers;

stores User objects by value. See What is object slicing?.

Thoughts

I'd also suggest templating the Manager on the concrete user type, but seeing how you use an actual type hierarchy, it seems you might be looking to actually use the runtime polymorphism.

Since serializing polymorphic types is somewhat more involved, let me show you a sample.

It also shows how to use e.g. boost::ptr_vector<> to manage the objects while storing them dynamically.

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();
    }
}

Prints

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


1 linking boost 1.59 is somehow failing there :( Thanks @m.s. for figuring out 1.58 still works

这篇关于升压连载子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆