C++/Creating class objects by reading text file
Expert: vijayan - 8/22/2008
QuestionQUESTION: Hi:
I want to create a class object by reading the text file. For example, if my text file has sentence "className A", then it should create that object A on the fly, again I also able to create multiple objects of same class by reading text file as explained above.
Can I do that?
Thanks,
Best Regards
ANSWER: in a simple scenario, you could do something like this:
#include <iostream>
#include <fstream>
#include <string>
class base
{
public:
virtual ~base() {}
virtual void save_state( std::ostream& stm ) const = 0 ;
virtual void restore_state( std::ostream& stm ) = 0 ;
virtual const std::string& identifier() const = 0 ;
};
//---------------------------------------------------------------------------------------
class A : public base
{
public:
A( std::istream& ) ;
virtual void save_state( std::ostream& stm ) const
{
// write the state of the object to stm
}
virtual void restore_state( std::ostream& stm )
{
// read the state from stm , set of the object to read values
}
virtual const std::string& identifier() const { return id ; }
static const std::string id ;
// other stuff
};
const std::string A::id = "className A" ; // unique id for class A
//---------------------------------------------------------------------------------------
class B : public base
{
public:
B( std::istream& ) ;
virtual void save_state( std::ostream& stm ) const
{
// write the state of the object to stm
}
virtual void restore_state( std::ostream& stm )
{
// read the state from stm , set of the object to read values
}
virtual const std::string& identifier() const { return id ; }
static const std::string id ;
// other stuff
};
const std::string B::id = "className B" ; // unique id for class B
//---------------------------------------------------------------------------------------
void save( const base* object, std::ostream& stm )
{
stm << object->identifier() << '\n' ;
object->save_state(stm) ;
}
base* create_from_stream( std::istream& stm )
{
base* object = 0 ;
std::string id ;
std::getline( stm, id ) ;
if( id == A::id ) return new A(stm) ;
else if( id == B::id ) return new B(stm) ;
// etc
return 0 ;
}
if you need more abstraction than this, use an exemplar (prototype) design pattern.
a very good discussion on implementing exemplars in C++ is available in:
Advanced C++ Programming Styles and Idioms by James O. Coplien
http://www.amazon.com/Advanced-C-Programming-Styles-Idioms/dp/0201548550
see chapter 8: Programming with Exemplars in C++ pages 279-306
---------- FOLLOW-UP ----------
QUESTION: Thanks for your quick reply. I am really appreciated.
I have couple of doubts:
1) where could call of the void save(..) and base* create_from_stream(..) lie? I mean which is the calling function, is it main()?
2)What are save_state and restore_state functions meant for?
Thanks,
Best Regards,
Dipen Patel
Answer> where could call of the void save(..) and base* create_from_stream(..) lie?
anywhere, really. if you are saving the objects into a file when your program exits and recreating the objects on restart, main would be a logical choice.
> What are save_state and restore_state functions meant for?
save_state should write out information about the object in such a way that the information can be read back later.
restore_state is the function that actually reads the saved information and modifies the member variables so that they corrospond to the state saved earlier.
for example:
class base
{
public:
virtual ~base() {}
virtual void save_state( std::ostream& stm ) const = 0 ;
virtual void restore_state( std::istream& stm ) = 0 ;
virtual const std::string& identifier() const = 0 ;
};
class Book : public base
{
public:
// constructor
Book( const std::string& _title, const std::string& _author, int _npages )
: title(_title), author(_author), npages(_npages) {}
// constructor to initialize from stream
Book( std::istream& stm ) { restore_state(stm) ; }
// write the state of the object to stm
virtual void save_state( std::ostream& stm ) const
{
// write out each data member to stream
// seperated by a newline
stm << title << '\n' << author << '\n' << npages << '\n' ;
}
// read the state from stm , set of the object to read values
virtual void restore_state( std::istream& stm )
{
// read each data member from stream (seperated by a newline)
// and set the values to member variables
std::string str ;
std::getline( stm, str ) ; title = str ;
std::getline( stm, str ) ; author = str ;
int n ;
stm >> n >> std::ws ;
npages = n ;
}
virtual const std::string& identifier() const { return id ; }
static const std::string id ;
// other members
private:
std::string title ;
std::string author ;
int npages ;
};
const std::string Book::id = "className Book" ; // unique id for class Book
notes:
1. error handling has been elided for brevity.
2. save_state should take an input stream
and restore_state should take an input stream (std::istream)
3. you could construct a std::ofstream to save to a file and a std::ifstream to read back from that file.