Advanced Tools Module User’s Guide : PART II Advanced Tools Module Packages : Chapter 6 Using Object Serialization : Basic Examples
Basic Examples
This section presents simple examples that illustrate the most common uses of object serialization. The earlier examples emphasize the intrusive method. External serialization support is similar (see “External Serialization”).
NOTE >> All code in this section comes from example source code distributed as part of the product. The source file appears in parentheses before the code sample.
Saving and Restoring an Object by Value
First, add serialization support. For example, suppose you start with an instance of class real_property:
 
class real_property
{
public:
real_property ();
 
real_property (const RWCString& address,
const RWCString& size);
 
private:
RWCString address_;
RWCString size_;
};
You need to make two changes to add serialization support.
First Change
Insert the RW_DECLARE_VIRTUAL_STREAM_FNS() macro into the class declaration. The name of the class must be provided as a parameter. Any declarations that appear below this macro are private. The following example shows the header file for real_property with the macro inserted.
 
// examples\serial\simple\real_property.h
 
class real_property
{
RW_DECLARE_VIRTUAL_STREAM_FNS(real_property) // 1
 
public: // 2
real_property() { } // 3
 
real_property (const RWCString& address, const RWCString& size)
: address_(address), size_(size) {
}
 
virtual ~real_property() { }
 
bool
operator== (const real_property&prop) const {
return address_ == prop.address_;
}
private:
RWCString address_;
RWCString size_;
};
//1 This macro declares streaming operators for the real_property class.
//2 Place the macro before anything else in the class. The macro assumes it is in a private scope, so it reinstates private as its last statement. If this public statement were ahead of the macro, the following constructors would be declared private.
//3 Object streaming requires a public default constructor.
Second Change
Define the streamContents() function for this class. Some of the macros that do this are:
RW_BEGIN_STREAM_CONTENTS()
RW_STREAM_PARENT()
RW_STREAM_ATTR_GET_SET()
RW_STREAM_ATTR_MEMBER()
RW_END_STREAM_CONTENTS()
Using these macros provides a built-in symmetry between the input and the output operations on the class. The macros defining the streamContents() function can be placed in any module, but are normally put in the same source file as the other definitions for that class. The following example from shows what it looks like for the real_property class.
 
// examples\serial\simple\real_property.cpp
 
RW_BEGIN_STREAM_CONTENTS(real_property) // 1
{
RW_STREAM_ATTR_MEMBER(address, address_) // 2
RW_STREAM_ATTR_MEMBER(size, size_)
}
RW_END_STREAM_CONTENTS // 3
//1 This macro begins the definition of the streamContents() function.
//2 This macro defines the code for inserting and extracting data to and from the address_ data member of the real_property class. The first parameter to the macro is an attribute label and need not match any name in the class, but the second parameter must be the actual name of the member that you want to stream. The macro is used again on the next line to accomplish the same thing for the size_ member.
//3 The streamContents() function is closed out with this macro.
Now that these macros have been added to real_property, this class can be written to and read from object streams using the operators operator<<(RWObjectOutputStream&, const real_property&) and operator>>(RWObjectInputStream&, real_property&), respectively. The following code shows how an instance of class real_property can be written to a file and read back.
 
// examples\serial\simple\real_estate.cpp
 
real_property real1("1980 Main St. Corvallis, Oregon","50x100"); // 1
real_property real2;
 
{ // 2
ofstream fout("real_estate.dat"); // 3
 
RWpostream posstr(fout);
RWObjectOutputStream out = RWCompactObjectOutputStreamImp::make(
RWDataToVirtualOutputStreamImp::make(
postr)); // 4
out << real1; // 5
}
 
ifstream fin("real_estate.dat"); // 6
RWpistream pistr(fin);
RWObjectInputStream in = RWCompactObjectInputStreamImp::
make(RWDataFromVirtualInputStreamImp::
make(pistr)); // 7
in >> real2; // 8
//1 Create a real_property object.
//2 Create a local scope so the output file closes automatically when it’s no longer needed.
//3 Open a file for output.
//4 Create a data stream using the standard file stream just opened and then create a compact object output stream from the data stream. The second parameter indicates the kind of object that will serve as the root element. It can be one of: objectTag, sequenceTag, or mapTag.
//5 Stream out the contents of real1 to the file in compact format.
//6 Now open the file for input.
//7 Create a data stream and then create a compact object input stream from the data stream.
//8 Read the data from the first variable (real1) into the second (real2).