Writing and reading objects with virtual methods to a binary file
<p>Hi I'm currently working on a simulation program that tries to save the state (variables and objects) of the program to a binary file when requested so that it can resume the simulation if needed.</p>

<p>Just as a note: I know that this is not compatible across different CPU architectures and that is absolutely fine!</p>

<p>Everything seemed to be working fine until it came to writing an object that has virtual methods to a file and then trying to reading it back.</p>

<p>The following code illustrates this problem:</p>

<p><strong>header.hpp</strong></p>

<pre><code>using namespace std;

class parent
{
        public:
                int mValue;
                virtual string getName() =0;
                virtual size_t getSize() =0;

                parent(int value) : mValue(value)
                {

                }
};

class bob : public parent
{
        public:
                bob(int value) : parent(value)
                {

                }

        string getName();
        size_t getSize() { return sizeof(bob); }
};

string bob::getName()
{
        string name("bob");
        return name;
}

class sarah : public parent
{
        public:
                sarah(int value) : parent(value)
                {

                }

        string getName();
        size_t getSize() { return sizeof(sarah); }
};

string sarah::getName()
{
        string name("sarah");
        return name;
}
</code></pre>

<p><strong>write.cpp</strong></p>

<pre><code>#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;string&gt;
#include "header.hpp"

int main()
{
    sarah girl(1);
    bob boy(2);

    parent* child1 = &amp;girl;
    parent* child2 = &amp;boy;

    cout &lt;&lt; "Created child called " &lt;&lt; child1-&gt;getName() &lt;&lt; endl;
    cout &lt;&lt; "Created child called " &lt;&lt; child2-&gt;getName() &lt;&lt; endl;

    //save sarah and bob to a binary file
    ofstream file("temp.bin", ios::binary | ios::trunc);

    if(!file.is_open())
            return 1;

    //format &lt;size&gt;&lt;data&gt;&lt;size&gt;&lt;data&gt;....
    size_t tempSize=0;

    //write child1
    tempSize = child1-&gt;getSize();
    file.write( (char*) &amp;tempSize,sizeof(size_t));

    file.write( (char*) child1,tempSize);

    tempSize = child2-&gt;getSize();
    file.write( (char*) &amp;tempSize,sizeof(size_t));

    file.write( (char*) child2,tempSize);

    file.close();

    return 0;
}
</code></pre>

<p><strong>read.cpp</strong></p>

<pre><code>#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;string&gt;
#include &lt;cstdlib&gt;
#include "header.hpp"

int main()
{

    //read sarah and bob from a binary file
    ifstream file("temp.bin", ios::binary);

    //format &lt;size&gt;&lt;data&gt;&lt;size&gt;&lt;data&gt;....
    size_t tempSize=0;

    //get size of child1
    file.read( (char*) &amp;tempSize, sizeof(size_t));

    //allocate memory for child1
    parent* child1= (parent*) malloc(tempSize);
    //read child 1 back
    file.read( (char*) child1,tempSize);

    //get size of child2
    file.read( (char*) &amp;tempSize, sizeof(size_t));

    //allocate memory for child2
    parent* child2= (parent*) malloc(tempSize);
    //read child 2 back
    file.read( (char*) child2,tempSize);

    file.close();

    //Using virtual methods causes SEGFAULT
    cout &lt;&lt; "Recreated child" &lt;&lt; child1-&gt;getName() &lt;&lt; endl;
    cout &lt;&lt; "Recreated child" &lt;&lt; child2-&gt;getName() &lt;&lt; endl;



    return 0;
}
</code></pre>

<p>And building and running as follows:</p>

<pre><code>g++ -g write.cpp -o write ; ./write
g++ -g read.cpp -o read  ; ./read
</code></pre>

<p>When I step through the read program in gdb I've noticed the problem appears to be the v-table pointer. When I recreate "sarah" (child1) in the read program the v-table pointer is the one that existed for the write program, not the read program. So presumably this v-table pointer for "sarah" in the write program points to an invalid region of memory which is causing the SEGFAULT.</p>

<p>I have two questions:</p>

<ul>
<li><p>Is it possible to save the v-table pointer information to the binary file in the "write" program so that my objects are perfectly recreated in the "right" program without resorting to a library such as Boost::Serialization or POST++ to handle this for me?</p></li>
<li><p>If it isn't possible ... or if it's quite complicated then I will have to add a constructor and a "saveState()" method (that can act on a ifstream and ofstream object respectively) so that each class (in this case sarah and bob) handles saving and reading it's state from a binary file. The problem with this is that I have multiple classes that are derived from the class "parent" so I would need a way for the "read" program to work out which constructor to call from reading the binary file. </p>

<p>I came up with one way of working out which constructor to call. This would be</p></li>
<li><p>Giving each class that derives from "parent" a unique ID</p></li>
<li>In the "write" program add unique ID to the binary file</li>
<li><p>In the "read" program read each unique ID and then use a switch statement to call the relevant constructor.</p>

<p>This isn't very elegant though as every time I add a new class that derives from "parent" I have to give it an ID and add it to the switch statement in "read". Is there a better way of doing it?</p></li>
</ul>

<p>Thanks for reading, I know my post is long!</p>
