Is there anyway to rebuild some saved classes from their vtable?

I copy some objects to a file, and they all come from the same class. but I want to be able to call their functions after loading them, to do what this class should do, here is what I have done so far:

#include <iostream> #include <fstream> using namespace std; struct a { virtual void print() { cout << "this is a.\n"; }; }; struct b : public a { virtual void print() { cout << "this is b.\n"; } }; int main() { ofstream testofile("test.bin",ios::binary); a* tempa = new a; a* tempb = new b; testofile.write((char*)tempa,sizeof(a)); testofile.write((char*)tempb,sizeof(b)); testofile.flush(); testofile.close(); ifstream testifile("test.bin",ios::binary); a* x = (a*)new char[max(sizeof(a),sizeof(b))]; testifile.read((char*)x,sizeof(a)); x->print(); testifile.read((char*)x,sizeof(b)); x->print(); } 

my example works fine, but if I comment on saving the part and then running the program, it seems that vtable is not valid for the newly launched application (although nothing has changed in my code). the problem is that my file manager class does not know about all the possible objects that can be extracted from my base object, and I want to rebuild the entire structure of the application using only one call to the file manager to load it. Of course, each of my objects has its own save / load functions, but how should the file manager guess where the load function is suitable for the current piece of data?

+4
source share
3 answers

Please do not do this. Never.

Basically, you use the old style to distinguish a* from char* . This gives silently in reinterpret_cast between two unrelated types and is highly implementation dependent . You cannot rely on a basic memory layout: it can change for any reason (even when using the same compiler).

If your class contains pointers, you have no guarantee that the data they point to will still be (or just the same) when you reload your class.

If you want to provide a serialization mechanism, create your own serialize() and deserialize() functions (they can even be template functions, which you can then specialize, or just regular member functions, it doesn't really matter).

Of course, this requires a little more work, but for the sake of reliability. In addition, you can optimize the presentation of data according to any type of storage (stored on disk, sent to the network ...), and you can even change your class interface and still maintain compatibility with already serialized instances.

+7
source

The code you write will not be portable (endianess).

As an example, the offset of the virtual function table can be changed by the offset of the base class or structure. The Solaris and Aix compiler puts vft at the end of struct / class and VC ++ at offset (0) in case of single inheritance. I never check with g ++, but you can have fun.

I do not recommend direct recording of an object if you do not have a large quantity and you do not need to store this data for a long time (i.e. temporary data).

The value of vft depends on where the dynamic library (dll or so) is displayed in virtual memory. If you write your own dispenser and fix vft, it may work. But this is pretty vague.

+1
source

You need a serialization mechanism by which your derived serialization method calls serialization on the base and then serializes first some identifier to indicate the derived type (typeid) and then its own members.
To restore objects from a serialized file, you need a factory object that reads the file and determines the type (derived from serialize typeid), initializes an object of this type, and calls the deserailize method on the object to load it from the file and return the object using the base class pointer.

0
source

All Articles