Virtual inheritance and polymorphism: Is the cereal library messing with object layout?
<p>I have four classes (<code>A</code>,<code>B</code>,<code>C</code> and <code>D</code>) following the classic diamond pattern and a <code>Container</code> class containing a <code>unique_ptr&lt;A&gt;</code>. I want to serialize these classes using the <a href="http://uscilab.github.io/cereal/" rel="nofollow">cereal</a> serialization library.</p>

<pre><code>struct A {int f1; int f2; int f3}

struct B : public virtual A {
    template&lt;typename Archive&gt;
    inline void save(Archive&amp; ar) const {
        std::cerr &lt;&lt; "Saving Obj: " &lt;&lt; this &lt;&lt; std::endl;
        std::cerr &lt;&lt; "This: " &lt;&lt; &amp;(this-&gt;f1) &lt;&lt; " " 
            &lt;&lt; &amp;(this-&gt;f2) &lt;&lt; " " &lt;&lt; &amp;(this-&gt;f3) &lt;&lt; std::endl;
        std::cerr &lt;&lt; "This: " &lt;&lt; this-&gt;f1 &lt;&lt; " " 
            &lt;&lt; this-&gt;f2 &lt;&lt; " " &lt;&lt; this-&gt;f3 &lt;&lt; std::endl;
    };
}
};

struct C : public virtual A {};

struct D : public B, public C {};

#include &lt;cereal/archives/binary.hpp&gt;
CEREAL_REGISTER_TYPE(B);
CEREAL_REGISTER_TYPE(C);
CEREAL_REGISTER_TYPE(D);

struct Container {
    std::unique_ptr&lt;A&gt; obj;

    template&lt;typename Archive&gt;
    inline void save(Archive&amp; ar) const {
        std::cerr &lt;&lt; "Saving Container" &lt;&lt; std::endl;
        std::cerr &lt;&lt; "Obj Addr: " &lt;&lt; obj.get() &lt;&lt; std::endl;
        std::cerr &lt;&lt; "Obj: " &lt;&lt; &amp;(obj-&gt;f1) &lt;&lt; " " &lt;&lt; &amp;(obj-&gt;f2) 
            &lt;&lt; " " &lt;&lt; &amp;(pq-&gt;f3) &lt;&lt; std::endl;
        std::cerr &lt;&lt; "Obj: " &lt;&lt; " " &lt;&lt; pq-&gt;sq_count &lt;&lt; " " &lt;&lt; pq-&gt;sq_bits 
            &lt;&lt; " " &lt;&lt; pq-&gt;dim &lt;&lt; std::endl;
        ar(obj); // Call serialization for obj, ie B.save(...)
    }
}
</code></pre>

<p>All classes have cereal <code>save</code> and <code>load</code> functions, but I only included them for <code>B</code> and <code>Container</code>, as they are the only ones used in this example.</p>

<p>I use these classes as follows :</p>

<pre><code>std::unique_ptr&lt;A&gt; obj(new B);
obj-&gt;f1 = 8;
obj-&gt;f2 = 8;
obj-&gt;f3 = 128;
std::unique_ptr&lt;Container&gt; db(new Container);
db.obj = std::move(obj);

std::ofstream out_file(out_filename);
cereal::BinaryOutputArchive out_archive(out_file);
out_archive(db);
</code></pre>

<p>And I get the following output:</p>

<pre><code>Saving Container
Obj Addr: 0x23d2128 
Obj: 0x23d2130 0x23d2134 0x23d2138 // Fields adresses (f1,f2,f3)
Obj:  8 8 128 // Fields values
Saving Obj: 0x23d2128 // Same object
This: 0x23d2118 0x23d211c 0x23d2120 // Different field adresses !
This: 4293296 0 37569440 // Garbage
</code></pre>

<p>My question is: Is it likely that this is a bug in cereal, or is there something that I don't get with virtual inheritance ?</p>

<p>Is it expected that the addresses of the fields of a given object ever change in a C++ program ?</p>