0

I perform serialization / deserialization of a subclass object by a pointer to its base class. Everything works Ok, yet I miss one feature: adding a runtime parameter to the constructor of the object being deserialized, example:

class Base {  
public:  
    Base(AnotherClass* another)  
        :m_another(another)  
    {}  
protected:  
    AnotherClass* m_another;  
};  
class Derived : public Base {  
public:  
    Derived(AnotherClass* another)  
        :Base(another)  
    {}  
    Derived()  
        :Base(nullptr)  
    {}  
private:  
    /* different other members */  
};  
BOOST_CLASS_EXPORT(Derived);  
...  

My normal way to create a Derived object is:

Base* obj = new Derived(anotherObj);  

The deserialization goes like this:

Base* obj;
ar >> obj;  

The default constructor will be called (Derived()), and deserialization proceeds, BUT m_another is not deserialized, it should be passed to the constructor, all the other fields are deserialized.
Moreover, I cannot set m_another after the deserialization, because it actually influences the deserialization.
I can pass reference to anotherObj via a global variable - ugly, but works.
Is there any way to solve it in a not so ugly manner ?

segfault
  • 489
  • 4
  • 16

1 Answers1

0

First off, to get polymorphic behaviour of the class you need have a polymorphic type. This logical requirement is stated in the documentation:

It turns out that the kind of object serialized depends upon whether the base class (base in this case) is polymophic or not. If base is not polymorphic, that is if it has no virtual functions, then an object of the type base will be serialized. Information in any derived classes will be lost. If this is what is desired (it usually isn't) then no other effort is required.

If the base class is polymorphic, an object of the most derived type (derived_one or derived_two in this case) will be serialized. The question of which type of object is to be serialized is (almost) automatically handled by the library.

[...]

The obvious way to enforce this is to have the virtual destructor (When to use virtual destructors?).


Next up, to (de)serialize types using a non-default constructor, use save_construct_data/load_construct_data. Again, the docs are a good start.

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • The class is polymorphic, thank you ! The problem is _load_construct_data()_ deserializes the params passed to the constructor, while I need runtime param. – segfault Jul 04 '18 at 19:12
  • Huh. So, you explicitly want to inject data not present in the archive? Why would it be a problem to serialize the `m_another` inside the `save_construct_data`? Object tracking with alias detection will do the rest automatically. I'd suggest creating a self-contained example showing what you have, and what you would like to happen instead. – sehe Jul 04 '18 at 22:43
  • It is a problem, because (in my case) _m_another_ is a pointer to an object that contains the object being deserialized. So (in my case) _m_another_ is deserialized earlier, and all I need is to pass pointer to _m_another_. – segfault Jul 05 '18 at 06:47
  • So? I already answered that. Are you trying to convince me that, no, your problem is hard or unsolvable? You're out of luck, because this site is about sharing solutions, not just problems. – sehe Jul 05 '18 at 12:17
  • Showing what you have would help. So in absence of that, let me make up some examples that should probably help you: [Object tracking just works](http://coliru.stacked-crooked.com/a/7dea4346e1dc3336). It will be slightly more cumbersome [with friend declarations if `m_another` is protected](http://coliru.stacked-crooked.com/a/cb689944ece1d3fc). – sehe Jul 05 '18 at 12:20
  • Regardless, object tracking still just works. To make that point all the way, it **even** works if you [have cyclic references back to the object being deserialized from inside the `OtherClass`](http://coliru.stacked-crooked.com/a/0107c8b3d01b5fb1). All the while without leaking or double serializations. Neat, huh? – sehe Jul 05 '18 at 12:21
  • Of course to be secure about the memory management it's better to use smart pointers. [That's not a problem either](http://coliru.stacked-crooked.com/a/60952376f15411fd) – sehe Jul 05 '18 at 12:27