PerryDK
asked on
Loading an array of Persistent pointers from a stream
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.
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(
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
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
}
else if(class_id == C2::class_id)
{
delete myArray[i];
myArray[i] = new C2();
myArray[i]->loadFromStream
}
}
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.
also check out s11n ... http://s11n.net/s11n/
ASKER
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.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
i was thinking on the same lines ie using rtti , but i am not sure how you can call loadFromStream from the base class
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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