home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
CPROG
/
CSTREAM.ZIP
/
CSTREAM.DOC
< prev
next >
Wrap
Text File
|
1991-05-28
|
8KB
|
260 lines
Dear C++ programmer,
Thank you for downloading csteam. The StreamableClass
class provides a base class for a polymorphic cluster
of streamable classes! In other words, any class
derived from the StreamableClass can be stored on a
stream and subsequently loaded from the stream later.
All such classes can be stored in any order and/or mix
on the same stream.
The inspiration for my StreamableClass comes from
Borland's TurboVision for Turbo Pascal, and there is no
telling where they got it! A TurboVision for BC++ has
been hinted at by Borland but cstream allows you to
stream classes without the whole TurboVision tool, and
to do it NOW! Not to mention it's FreeWare.
Getting Started
===============
Copy cstream.hpp to your header directory and
cstream.cpp along with csdemo.cpp to your source
directory. Compile cstream.cpp and csdemo.cpp and link
(a project file is included, i.e. csdemo.prj). Run
this demo and study its source.
In order to make a class streamable, derive it
privately from StreamableClass.
class Employee : StreamableClass {
...
public:
StreamableClassID(2);
...
Employee();
~Employee();
};
The StreamableClassID macro is used to assign a unique
id by which the class can be identified on the stream.
This macro also declares several required member
functions of which you must define store() and load().
Below is the macro definition as it appears in
cstream.hpp.
#define StreamableClassID(id) \
enum { CLASS_ID = id }; \
StreamableClass::ID; \
operator StreamC() { return (StreamC)this; } \
virtual void store(ostream& os); \
static StreamC load(istream& is, StreamC C)
Your store function should write out to "os" the data
members of your class, specifically the data needed in
a call to a constructor for your class and any other
data required to reconstruct your class to its present
state. You'll see what I mean when you get to the
description for load(). Don't worry about the id or
any fields in StreamableClass - this is handled
automatically.
void Employee::store(ostream& os)
{
os << name << endf << address << endf
<< cityStateZip << endf;
}
Your load function should read in the data stored in
the extact order it was written out.
StreamC Employee::load(istream& is, StreamC C)
{
char *name, *address, *cityStateZip;
if (C)
return C;
is.getline(nameBuf,MAX_STR_BUF,
StreamableClass::FieldTermChar);
is.getline(addressBuf,MAX_STR_BUF,
StreamableClass::FieldTermChar);
is.getline(cityStateZipBuf,MAX_STR_BUF
,StreamableClass::FieldTermChar);
return new Employee(nameBuf,addressBuf,
cityStateZipBuf);
}
The load() function then calls your class' constructor
with the new operator to create the class. If any
other information is required modify your class to
conform to its prestorage state, that information will
obviously have to be read in and the appropriate
modification made. Make sure your store() function
stores this information.
The trick to streamable classes is in the load()
function. It is a static member of StreamableClass and
thus has no implicit "this" parameter. The address of
a static function can be taken where as the address of
a constructor cannot be! This is why load() is declared
as such. Note also that load returns "StreamC", a
pointer to a StreamableClass base. All we know when
loading a StreamableClass is that it is a
StreamableClass. You must call the ID() member
function, which returns the unique id you defined in
the StreamableClassID() macro, to determine its class.
If your class is not directly derived from
StreamableClass, it still needs to use the
StreamableClassID() macro. Your store() function
should call its immediate base class store() function
first before storing its own data members. The load()
function is alittle different. It still should call
its constructor and then it can call its base class
load() function to get any additional information
required. This is why I have the test "if (C)" in
Employee::load() above. You need to think your
hierarchical design out thoroughly. What is the access
to your base class' data members? Only data that can't
be accessed directly, through constructors, or member
functions, should be processed by the base's load()
inside "if (C) ..."!
The design of streamable classes in C++ requires that
we call a constructor - how else can we insure a
portable way of initializing virtual function table
addresses?
You should be wondering at this point how the correct
static load() function will be called. We need to back
up first and see how to initialize the whole
class-stream system. This is done by a global call to
the macro StreamableClasses().
StreamableClasses(20);
main()
{
RegisterClass(StreamableClass);
RegisterClass(Employee);
...
StreamableClass *S1, *S2, *S3;
ifstream iS("emp$prod.cls");
iS >> S1 >> S2 >> S3;
//S1->ID()
}
The call here initializes the system to hold a maximum
of 20 records for different streamable classes in our
application. You should set your count appropriately.
The classes to be streamed must be registered before
attempting to stream them with a call to the macro
RegisterClass(). Besure to always register the
StreamableClass for classes that may for some reason
not provide a load() function. The RegisterClass()
macro registers your class' ID and load function.
When you go to read back in classes from a stream,
define some pointers to StreamableClass and then fetch
the classes from the stream to these pointers. To
determine the actual class fetched, call the ID()
member function.
Registration
============
If you find cstream useful and are using it in your
applications, tell your friends. You don't need to
register cstream -- it's freeware! All I ask is that
you leave my copyright notice intact! How about
dropping me a line -- I like to here your comments and
suggestions.
Other Freeware Goodies available for Borland C++
=======================================================
pckey PC keyboard class w/auto enhanced
gconio Graphics mode conio class
cmouse Mouse Driver class w/ intr handler
cmdln Command line parser class
And Shareware
=============
FlexList II ANSI && K&R C
FlexList II C++
* Ready-to-run C/C++ linked lists.
* Hybrid structure: stack,queue,list,array.
* Stores Heterogeneous/homogeneous data
* Eliminates the need for parameterized list
templates such as are proposed for
C++ in the future.
Loose Data Binder C++
* Combination FlexList/TCollection
Soon to be Released
===================
PolyMesh II C++
* Networks of Polymorphic clusters
Thanks again!
John W. Small
CIS: 73757,2233
PSW / Power SoftWare
P.O. Box 10072
McLean, VA 22102 8072
USA (703) 759-3838