EDIT: I realised that the code below is a good example of what you cannot do in C++ with anything that is not a POD.
There doesn't seem to exist a way to escape from having a typeid into the classes and do some sort of switch or table lookup (both of which must be carefully maintained) on the receiver side to rebuild the objects.
I have wrote some toy code to serialise objects and two separate mains to write/read them to/from a file.
common.h:
#include <iostream>
using namespace std;
template <typename T>
size_t serialize(std::ostream & o, const T & t) {
const char * bytes = reinterpret_cast<const char*>(&t);
for (size_t i = 0; i < t.size(); ++i) {
o << bytes[i];
}
return t.size();
}
size_t deserialize(std::istream & i, char * buffer) {
size_t len = 0;
char c;
while (i.get(c)) {
buffer[len] = c;
++len;
}
return len;
}
// toy classes
struct A {
int a[4];
virtual ~A() {}
virtual void print(){cout << "A\n";}
virtual size_t size() const {return sizeof(*this);}
};
struct B: A {
int b[16];
virtual ~B() {}
virtual void print(){cout << "B\n";}
virtual size_t size() const {return sizeof(*this);}
};
out.cpp:
#include <fstream>
#include "common.h"
int main() {
B b;
A& a = *static_cast<A*>(&b);
ofstream ofile("serial.bin");
cout << "size = " << serialize(ofile, a) << endl;
ofile.close();
return 0;
}
in.cpp:
#include <fstream>
#include "common.h"
int main() {
char buffer[1024];
ifstream ifile("serial.bin");
cout << "size = " << deserialize(ifile, buffer) << endl;
ifile.close();
A& a = *reinterpret_cast<A*>(buffer);
a.print();
return 0;
}
If my classes have no virtual functions, this appears to work fine, but
in.cpp
crashes when they do.
My understanding is that the vptr created by out.cpp
is not fine to be used by in.cpp
.
Is there something that could be done, possibly avoiding to manually create and maintain a vtable?