Virtual Functions saveGuts(RWFile&) and saveGuts(RWvostream&)
The saveGuts(RWFile&) and saveGuts(RWvostream&) virtual functions are responsible for polymorphically saving the internal state of an RWCollectable object on either a binary file, using class RWFile, or on a virtual output stream, using class RWvostream. For a description of the persistence mechanism, see Chapter 8. This allows the object to be restored at some later time, or in a different location. Here are some rules for defining a saveGuts() function:
1. Save the state of your base class by calling its version of saveGuts().
2. For each type of member data, save its state. How to do this depends upon the type of the member data:
*Primitives. For primitives, save the data directly. When saving to RWFiles, use RWFile::Write(); when saving to virtual streams, use the insertion operator RWvostream::operator<<().
*Rogue Wave classes. Most Rogue Wave classes offer an overloaded version of the insertion operator. For example, RWCString offers:
 
RWvostream& operator<<(RWvostream&,
const RWCString& str);
Hence, many Rogue Wave classes can simply be shifted onto the stream.
*Objects inheriting from RWCollectable. For most of these objects, use the global function:
RWvostream& operator<<(RWvostream&,
const RWCollectable& obj);
This function will call saveGuts() recursively for the object.
With these rules in mind, let's look at a possible definition of the saveGuts() functions for the Bus example:
 
void Bus::saveGuts(RWFile& f) const {
RWCollectable::saveGuts(f); // Save base class
f.Write(busNumber_); // Write primitive directly
f << driver_ << customers_; // Use Rogue Wave-
// provided versions
f << passengers_; // Will detect nil pointer
// automatically
}
void Bus::saveGuts(RWvostream& strm) const {
RWCollectable::saveGuts(strm); // Save base class
strm << busNumber_; // Write primitives directly
strm << driver_ << customers_; // Use Rogue Wave
// provided versions
strm << passengers_; // Will detect nil pointer
// automatically
}
Member data busNumber_ is an int, a C++ primitive. It is stored directly using either RWFile::Write(int), or RWvostream::operator<<(int).
Member data driver_ is an RWCString. It does not inherit from RWCollectable. It is stored using:
 
RWvostream& operator<<(RWvostream&, const RWCString&);
Member data customers_ is an RWSet. It does inherit from RWCollectable. It is stored using:
 
RWvostream& operator<<(RWvostream&, const RWCollectable&);
Finally, member data passengers_ is a little tricky. This data is a pointer to an RWSet, which inherits from RWCollectable. However, there is the possibility that the pointer is nil. If it is nil, then passing it to:
 
RWvostream& operator<<(RWvostream&, const RWCollectable&);
would be disastrous, as we would have to dereference passengers_:
 
strm << *passengers_;
Instead, since our class has declared passengers_ as an RWSet*, we pass it to:
 
RWvostream& operator<<(RWvostream&, const RWCollectable*);
which automatically detects the nil pointer and stores a record of it.