Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!mit-eddie!apollo!laporta From: laporta@apollo.uucp (John X. Laporta) Newsgroups: comp.lang.c++ Subject: Disk save/restore of derived class objects Message-ID: <36ed1da2.c449@apollo.uucp> Date: Thu, 27-Aug-87 18:16:00 EDT Article-I.D.: apollo.36ed1da2.c449 Posted: Thu Aug 27 18:16:00 1987 Date-Received: Sat, 29-Aug-87 12:14:13 EDT Reply-To: laporta@apollo.UUCP (John X. Laporta) Organization: Apollo Computer, Chelmsford, MA Lines: 81 Derived classes with virtual functions pose a problem for disk save and restore. Standard software techniques allow easy transformation of memory objects into disk objects, but the value of the _vptr member of derived classes in which virtual functions are defined is program-specific in environments where the class library is bound in with the program. This complicates save and restore considerably, since a _vptr written by one program is invalid when read by another. One technique for solving this problem follows. Consider this pair of classes: class base { int member; public: virtual void set_member(){member = 1;} }; class derived:public base { int other_member(); public: void set_member(){member = other_member;} }; Class derived now has a member _vptr whose type is undefined. If program A writes copies of objects of class derived to disk, and program B reads these copies in, any call to derived::set_member() can cause serious problems, because the _vptr member that was valid for program A will almost certainly be invalid for program B. Add a derived type enumeration, a type field in class base, and a friend function void base_set_vptr(base*) of class base as follows: int enum class_type { base_type, derived_type}; class base { int type; int member; friend void base_set_vptr(base*); public: virtual void set_member(){member = 1}; }; Add the appropriate assignment to the type field to constructors for the base and derived classes. Then define void base_set_vptr(base*) as follows: void base_set_vptr(base* new_base) { static derived *derived_dummy; if (NULL == derived_dummy) // on first call only derived_dummy = new derived; if (derived_type == new_base->type) // reset _vptr if any new_base->_vptr = derived_dummy->_vptr; } When saving a copy of class derived to disk, employ another friend function, void base_null_vptr(base*): void base_null_vptr(base* new_base) { if (derived_type == new_base->type) new_base->_vptr = NULL; } and two copies of the same instance of class derived written by different programs will be identical on disk. It would be possible to have one friend function: void base_set_vptr(base* new_base, ptr) if the type of _vptr were known, but as B. Stroustrup says on pages 202-203: Clearly implementing [virtual functions] will involve storing some kind of type information in each object of class employee. The space taken (in the *current implementation*) is just enough to hold one pointer. (Italics mine.) It appears Stroustrup is not guaranteeing against change in the type of the _vptr member. Isolating the assignment in these friend functions should minimize the pain of transition between implementations. Does anyone know a simpler or better solution?