We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Loading an array of Persistent pointers from a stream

PerryDK
PerryDK asked
on
Medium Priority
381 Views
Last Modified: 2008-03-06
This may be better off in the c++ thread but I think it relates to all object-orientated languages.

class Stream;
//Implementation isn't important just realize it supports reading and writing of all primitive types and a few higher level objects such as strings, etc.

class Persistent
{
public:
  Persistent();
  virtual ~Persistent();

  virtual void saveToStream(Stream& s);
  virtual void loadFromStream(Stream& s);
};

For those who aren't familar with the term persistent it basically means that it is a class that knows how to read and write it self to a stream.  Again implementation of this class isn't really all that important.  Notice that it implements virtual methods for saving a loading an instance of this class to a stream.

class C1 : public Persistent
{
public:
  C1();
  ~C1();

  virtual void saveToStream(Stream& s);
  virtual void loadFromStream(Stream& s);
};

Notice that class is a derived class from the Persistent class which provides its own virtual methods for saving and loading information to a stream.

Consider the following 2 examples which work just fine:

Example 1:
C1 myArray[10];
//initialize all C1 class instances with whatever not important.

Stream s;
//save the data to the stream
for(int i = 0; i < 10; i++)
  myArray[i].saveToStream(s);
s.setPosition(0); // set the stream back to the beginning
for(int i = 0; i < 10; i++)
  myArray[i].loadFromStream(s);

Example 2:
C1* myArray[10];
//initialize all C1 class instances with whatever not important and make sure the pointers are created.

Stream s;
//save the data to the stream
for(int i = 0; i < 10; i++)
  myArray[i]->saveToStream(s);
s.setPosition(0); // set the stream back to the beginning
for(int i = 0; i < 10; i++)
  myArray[i]->loadFromStream(s);

Both examples working flawlessly.


Now for the BIG QUESTION!!!
lets say I have a class C2 defined as

class C2 : public Persistent
{
public:
  C2();
  ~C2();

  virtual void saveToStream(Stream& s);
  virtual void loadFromStream(Stream& s);
};

and I have an array defined as such
Persistent* myArray[10];

myArray now holds pointers to class instances of Persistent or any class instance which has publicly derived from the class Persistent.

Saving data is no big deal
for(int i = 0; i < 10; i++)
  myArray[i]->saveToStream(s);

Well maybe saving data is no big deal I'll get back to that in a second.
Now how would I go about loading in myArray from a stream?  The stream data may be instance of C1 or instance of C2.

One possible solution I came up with is to have a const static datameber such as class_ID and do this

//save data
for(int i = 0; i < 10; i++)
{
  s << myArray[i]->class_ID;
  myArray[i]->saveToStream(s);
}

//load data
for(int i = 0; i < 10; i++)
{
  int class_id;
  s >> class_id;
  if(class_id == C1::class_id)
  {
    delete myArray[i];
    myArray[i] = new C1();
    myArray[i]->loadFromStream(s);
  }
  else if(class_id == C2::class_id)
  {
    delete myArray[i];
    myArray[i] = new C2();
    myArray[i]->loadFromStream(s);
  }
}

I don't really like this approach.  For each new decedent of Persistent I have to create a const static class_id.  And I have to make sure that no other classes that decedend from Persistent use this class_id.

I know this is an extremly difficult question so I will reward 500 points to all people who can provide an elegant solution to this problem.  Something that would require little maintenace of code.  That is I don't want to go and look through all my classes that decend from Persistent and make sure they don't have the same class_id as a new class that I am making and assign a different class_id.

a class_id may not is more than likely not an elegant way of solving this problem.  I'm thinking a template class or some sort of class factory may be more eligant but don't really know where to start.  Just throwing out some ideas.
Comment
Watch Question

Hi Perry,
I havent tried it myself, but in case you are using MFC ..... you can derive your class from CObject and it will work like serialized objects in java .
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_core_serialization.3a_.serializing_an_object.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmfc98/html/_mfcnotes_tn002.asp

HTH
also check out s11n ... http://s11n.net/s11n/

Author

Commented:
I am not using MFC.  I am using Borland C++ Builder...but the answer to this question should be ANSI C++ compliant.  I want it to be a portable solution.
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
i was thinking on the same lines ie using rtti , but i am not sure how you can call loadFromStream from the base class
efn
Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.