IMStreamable is a virtual base class that must be mixed into all classes that support polymorphic streaming. It introduces virtual read-from and write-to stream functions that all subclasses must override. To create a streamable class, you must derive from IMStreamable and implement the streaming functions.
IStreamModule provides a way to group classes together or to qualify a class name. It provides a context for objects on a stream to distinguish a class in one DLL from a class with the same name in another DLL. Typically you will define one stream module for each DLL or application. This will eliminate name conflicts and avoid cross-DLL dependencies.
Every IMStreamable class, as part of its definition, must specify the stream module to which it belongs.
StreamableDeclarationsMacro must appear as the first item inside the declaration of all concrete classes that derive from IMStreamable. Abstract classes deriving from IMStreamable must not include this macro.
StreamableDefinitionsMacro must appear in the implementation .cpp file for all concrete classes that derive from IMStreamable. It identifies the IStreamModule to which the class belongs. Abstract classes deriving from IMStreamable must not include this macro.
To declare and define a streamable class, including its streaming functions, follow these steps:
In your class header file, include the declaration of IMSTREAMABLE:
#include <imstrmbl.hpp>
Declare your class as a subclass of IMSTREAMABLE:
class IMyClass : public IMyBase, public IMSTREAMABLE { StreamableDeclarationsMacro(IMyClass); private: // This is class instance data that must be // streamed by the streaming operators. int fData; ISomeType* fObjectPointer; IAnotherType* fAnotherObjectPointer; IBaseType* fAbstractBasePointer; ISomeType fEmbeddedObject; short fShortArray[123]; ISomeType fSecondVersionObject; public: IMyClass(); // Normal user class ... virtual ~IMyClass();
protected: virtual void writeToStream(IDataStream& toWhere) const; virtual void readFromStream(IDataStream& fromWhere); };
Add the following line to your .cpp file:
StreamableDefinitionsMacro(IMyClass, gMyStreamModule);
void IMyClass::writeToStream(IDataStream &toWhere) const { // Stream Frame local variable. Scope must enclose the writing of all // data by this stream out operator. IStreamOutFrame myFrame(toWhere); // Stream out the base class. // Base class streaming is the one case where // writeToStream is used directly, instead of operator >>= IMyBase::writeToStream(toWhere); // Stream out the data fields. fData >>= toWhere; // A primitive type (an int). *fObjectPointer >>= toWhere; // fObjectPointer must refer to // a valid object. This streams the // object monomorphically. // Stream this object monomorphically. The type parameter is // the actual type of the object being streamed. // Handle nil pointers correctly. ::writeObject(fAnotherObjectPointer, toWhere); // Always stream this object polymorphically. ::writeObject(fAbstractBasePointer, toWhere); // Embedded objects always use the streaming operators. // They don't need, and can't use, the nil pointer test // and heap allocation performed by read or write object. fEmbeddedObject >>= toWhere; // Write the array of shorts. toWhere.writeShorts(fShortArray, 123); // This object was added to the stream format after the initial //release. fSecondVersionObject >>= toWhere; };
void IMyClass::readFromStream(IDataStream &fromWhere) { // Create a local instance of IStreamInFrame. IStreamInFrame myStreamFrame(fromWhere); // Stream in the base class. IMyBase::readFromStream(fromWhere); // Stream in the data fields. fData <<= fromWhere; // A primitive type (an int). *fObjectPointer <<= fromWhere; // fObjectPointer must refer // to a valid object. // Monomorphically stream in an object. // Handle nil pointers correctly. delete fAnotherObjectPointer; ::readObject(fAnotherObjectPointer, fromWhere, IAnotherType::staticTypeRepresentation); // Polymorphic readObject. Stream always specifies // the actual type of object to read. delete fAbstractBasePointer; ::readObject(fAbstractBasePtr, fromWhere); fEmbeddedObject <<= fromWhere; // Read the array of shorts. Must know the size and have // storage available before calling any array read function. fromWhere.readShorts(fShortArray, 123); // fSecondVersionObject may or may not be on the stream // depending on which version of the class wrote to the // stream. if (!myStreamFrame.atEnd()) { fSecondVersionObject <<= fromWhere; } };
Introduction
to the Streaming Classes
Aliased
Objects
Monomorphic
Streaming
Polymorphic
Streaming
Release-to-Release
Data Compatibility (RRDC)
Data
Streams
Application
Data Interfaces
Adding Streaming Support
to Structs and Simple Classes
Creating a Streamable
Template Class
Instantiating a
Stream Module
Enabling
Release-to-Release Data Compatibility
Streaming Base Classes
Streaming
Aliases and Aliased Objects
Streaming
Objects Monomorphically
Streaming
Objects Polymorphically
Transitioning from
Older Streaming Constructs