Boost serialization of derived class with private members

前端 未结 2 1112
时光取名叫无心
时光取名叫无心 2021-01-24 07:10

I try to serialize a class, say B (in file b.h), which is derived from another one, say A (in file a.h). Both classes have private members and I want to serialize both with the

相关标签:
2条回答
  • 2021-01-24 07:12

    Now I got it: Non-intrusive serialization (text format) with a pimpl style struct as described paragraph 3 here let most members private and reduced the overhead of get/set methods. xml is still open - got compiler errors C2664 and C2789 on Visual Studio 2015. Also json could be interesting ...

    0 讨论(0)
  • 2021-01-24 07:21

    First, a fair warning about Quasi-Classes (PDF). They are the enemy of encapsulation and confuse OOP.

    Next, let me answer two of your questions real quick and proceed to show my take on this:

    1. Q. where to put it in the non-intrusive case (save/load/serialize or all three?)?

      Either in serialize OR in both save and load (if you have split implementations)

    2. Q. what object has to been used in place of the this pointer?

      The same object. If you do member-function serialize this points to the same object as gets passed the free function as the second argument. Just use that object.

    My Take

    Now, let me refer to my answer to Get private data members for non intrusive boost serialization C++

    Here's a demonstration of the idea Tanner suggested in his comment

    Live On WandBox

    • a.h

      #pragma once
      
      class A {
      private:
          int elemA;
      
      public:
          A(int elem = 0) : elemA(elem) {};
          virtual ~A() = default;
      
          int getElemA() const { return elemA; }
          void setElemA(int elem) { elemA = elem; }
      };
      
    • b.h

      #pragma once
      #include "a.h"
      
      class B : public A {
      private:
          int elemB;
      
      public:
          B(int elem = 0) : A(42), elemB(elem) {};
      
          int getElemB() const { return elemB; }
          void setElemB(int elem) { elemB = elem; }
      };
      
    • main.cpp

      #include <string>
      #include <sstream>
      #include <iostream>
      
      #include <boost/archive/text_oarchive.hpp>
      #include <boost/archive/text_iarchive.hpp>
      #include <boost/serialization/base_object.hpp>
      #include <boost/serialization/export.hpp>
      #include "b.h"
      
      BOOST_CLASS_EXPORT(A)
      BOOST_CLASS_EXPORT(B)
      
      namespace privates {
      
          template <typename Key, typename Key::type PointerToMember> struct store {
              friend typename Key::type get(Key) { return PointerToMember; }
          };
      
          struct elemA {
              typedef int A::*type;
              friend type get(elemA); // ADL-enable
          };
      
          struct elemB {
              typedef int B::*type;
              friend type get(elemB); // ADL-enable
          };
      
          template struct store<elemA, &A::elemA>;
          template struct store<elemB, &B::elemB>;
      
      } // namespace privates
      
      auto& getElemA(A& instance) { return instance.*(get(privates::elemA())); }
      auto& getElemB(B& instance) { return instance.*(get(privates::elemB())); }
      
      namespace boost {
          namespace serialization {
              template<class Archive>
              void serialize(Archive & ar, A& v, unsigned) { ar & getElemA(v); }
      
              template<class Archive>
              void serialize(Archive & ar, B& v, unsigned) { ar & base_object<A>(v) & getElemB(v); }
          }
      }
      
      template <typename T> void run_tests() {
          std::stringstream ss;
          {
              A *obj= new T(747);
              boost::archive::text_oarchive oa(ss);
              oa << obj;
              delete obj;
          }
      
          std::cout << ss.str() << "\n";
      
          {
              A *obj = nullptr;
              boost::archive::text_iarchive ia(ss);
              ia >> obj;
              delete obj;
          }
      }
      
      int main()
      {
          run_tests<A>();
          run_tests<B>();
      }
      

    Note it simplifies a few things and at least removed memory-leaks when there were no exceptions.

    Output Live On WandBox

    22 serialization::archive 15 0 1 0
    0 747
    
    22 serialization::archive 15 1 1 B 1 0
    0 1 0
    1 42 747
    
    0 讨论(0)
提交回复
热议问题