代码之家  ›  专栏  ›  技术社区  ›  Michał Hanusek

谷物的系列化与遗传

  •  -1
  • Michał Hanusek  · 技术社区  · 6 年前

    我希望我的程序在JSON文件中保存和读取配置结构。

    但是,我在生成正确的JSON文件时遇到问题。可能问题在于继承。

    JSON输出(不正确):

      {
            "config": {
                "confVector": [
                    {
                        "common": "a"
                    },
                    {
                        "common": "b"
                    }
                ]
            }
        }
    

    预期(正确)JSON:

      {
            "config": {
                "confVector": [
                    {
                        "common": "a",
                        "a" : 1
                    },
                    {
                        "common": "b",
                        "b" : "b"
                    }
                ]
            }
        }
    

    代码:

    具有公共元素的基结构

    struct Base
    {
        std::string common;
    
        template <class Archive>
        void serialize(Archive &ar)
        {
            ar(CEREAL_NVP(common));
        }
    };
    

    两种特殊结构

    struct A : public Base
    {
        int a;
    
        template <class Archive>
        void serialize(Archive &ar)
        {
            ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
            ar(cereal::make_nvp("a", a));
        }
    };
    
    struct B : public Base
    {
        std::string b;
    
        template <class Archive>
        void serialize(Archive &ar)
        {
            ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
            ar(cereal::make_nvp("b", b));
        }
    };
    
    struct Config
    {
        std::vector<Base> confVector;
    
        template <class Archive>
        void serialize(Archive &ar)
        {
            ar(CEREAL_NVP(confVector));
        }
    };
    CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, A)
    CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, B)
    

    主:测试保存到JSON文件

    int main()
    {
        std::string workPath = MAKE_STR(PLC_PROGRAM);
    
        Config config;
    
        A a;
        a.a      = 1;
        a.common = "a";
    
        B b;
        b.b      = "b";
        b.common = "b";
    
        config.confVector.push_back(a);
        config.confVector.push_back(b);
    
        std::ofstream outstream;
        outstream.open(workPath + "/test.json");
    
        {
            cereal::JSONOutputArchive ar(outstream);
            ar(cereal::make_nvp("config", config));
        }
    
        outstream.close();
    }
    
    2 回复  |  直到 6 年前
        1
  •  0
  •   Loki Astari    6 年前

    你的物体正在被切割。

    std::vector<Base> confVector;
    

    这是类型对象的向量 Base .
    如果将派生自 基地 然后它只复制对象的基础部分。

    A a;
    B b;
    config.confVector.push_back(a);  // a is of Type A not Base
    config.confVector.push_back(b);  // b is of type B not Base
    

    所以当把这两个物体放到向量中时,它们都被切片了。

    可以存储指向对象的指针:

    std::vector<Base> confVector;
    ...
    config.confVector.push_back(&a);
    config.confVector.push_back(&b);
    
        2
  •  0
  •   Michał Hanusek    6 年前

    我解决了这个问题。

    struct Base
    {
        Base()          = default;
        virtual ~Base() = default;
    
        std::string common;
    
        template <class Archive>
        void serialize(Archive &ar)
        {
            ar(CEREAL_NVP(common));
        }
    };
    
    struct A : public Base
    {
        A() = default;
    
        A(int v)
        {
            a = v;
        }
    
        int a;
    
        template <class Archive>
        void serialize(Archive &ar)
        {
            ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
            ar(a);
        }
    };
    
    struct B : public Base
    {
        B() = default;
    
        B(std::string text)
        {
            b = text;
        }
    
        std::string b;
    
        template <class Archive>
        void serialize(Archive &ar)
        {
            ar(cereal::make_nvp("Base", cereal::base_class<Base>(this)));
            ar(b);
        }
    };
    
    struct Config
    {
        std::vector<std::shared_ptr<Base>> vector;
    
        template <class Archive>
        void serialize(Archive &ar)
        {
            ar(vector);
        }
    };
    
    CEREAL_REGISTER_TYPE(A)
    
    CEREAL_REGISTER_TYPE_WITH_NAME(B, "ClassB")
    
    CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, A)
    CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, B)
    
    int main()
    {
    
        std::string workPath = "/home/user/"
    
        {
            std::ofstream os(workPath + "polymorphism_test.json");
            cereal::JSONOutputArchive oarchive(os);
    
            std::shared_ptr<Base> ptr1 = std::make_shared<A>(123);
            std::shared_ptr<Base> ptr2 = std::make_shared<B>("foobar");
    
            Config op;
            op.vector.push_back(ptr1);
            op.vector.push_back(ptr2);
    
            oarchive(op);
        }
    
        {
            std::ifstream is(workPath + "polymorphism_test.json");
            cereal::JSONInputArchive iarchive(is);
            Config ip;
            iarchive(ip);
        }
    
        return 0;
    }
    

    输出:

    {
        "value0": {
            "value0": [
                {
                    "polymorphic_id": 2147483649,
                    "polymorphic_name": "A",
                    "ptr_wrapper": {
                        "id": 2147483649,
                        "data": {
                            "Base": {
                                "common": ""
                            },
                            "value0": 123
                        }
                    }
                },
                {
                    "polymorphic_id": 2147483650,
                    "polymorphic_name": "ClassB",
                    "ptr_wrapper": {
                        "id": 2147483650,
                        "data": {
                            "Base": {
                                "common": ""
                            },
                            "value0": "foobar"
                        }
                    }
                }
            ]
        }
    }