Solved

writing an object to a file

Posted on 2000-03-21
7
175 Views
Last Modified: 2012-05-04
I have an polymorphic object.  I'm trying to allow the user of my program to save the object for future use.

The base class of the object has a bunch of subclasses and some virtual methods.  The derived classes have subclasses.  I want to save the instances of the derived classes that the user creates by using the program.  How would i go about doing this?  The filestream methods dont seem to be working properly.
0
Comment
Question by:andrew161
  • 5
7 Comments
 
LVL 5

Expert Comment

by:Jan Louwerens
ID: 2641443
What you describe is called object serialization. I know this doesn't answer your question, but it might help you to narrow down your search for more info.
0
 
LVL 22

Accepted Solution

by:
nietod earned 250 total points
ID: 2641497
This is not hard to do if you will always be writting out and reading in the the same type object.  (there are cases where this is not true, where you will write objects of a certain type OR of types derived from that type.  If this is the case you have, let me know.  it is a little more complex.)

There are lots of ways to handle this, but one of the the best ways to handle it is to write input and ouput functions for all the classes involved.

Example follows.
0
 
LVL 5

Expert Comment

by:pitonyak
ID: 2641507

There are many ways to do this.... One common method is as follows:

For every class, define virtual functions called read_data and write_data.

Assume something like this...

class BaseClass {
public:
   ostream& write_data(ostream& os) const;
   istream& read_data(istream& is);

protected:
};

ostream& BaseClass::write_data(ostream& os) const
{
    // stream all of the data from this class to the ostream.
   return os;
}

istream& BaseClass::read_data(istream& is)
{
    // stream all of the data from this class from the istream.
   return is;
}

class D : public BaseClass {
public:
   ostream& write_data(ostream& os) const;
   istream& read_data(istream& is);

protected:
   BaseClass object_;
   int x_;
};

ostream& D::write_data(ostream& os) const
{
    // stream all of the data from this class to the ostream.
    // remember that I have not run this code to work out the bugs.
   BaseClass::write_data(os);
   object_.write_data(os);
   os << x_ << endl;
   return os;
}

istream& D::read_data(istream& is)
{
    // stream all of the data from this class from the istream.
    // remember that I have not run this code to work out the bugs.
   BaseClass::read_data(os);
   object_.read_data(os);
   os >> x_; // remember to eat the endl... verify the best way to do this.
   return is;
}


This, of course, assumes that you know exactly what you have written and
in what order. You may have to do things in a more complicated manner including type indentifiers and then have a class builder...

Andy
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 22

Expert Comment

by:nietod
ID: 2641528
Int the following example, the base class and the derived classes both defien input() and output() functions that allow the classes to be read and written.  The derived classes uses the base class version of the procedures to help it do it s work.

class Base
{
   int BX;
   double BD;
public:
   // output function
   void Output(ostream &Out)
   {
      Out << ' ' << BX << '  ' << BD; // Write the data members.
   };
   // Input function.
   void Input(istream &In)
   {
      In >> BX >> BD; // Read data members.
   };
};

class Derived : public Base
{
   int DX;
   double DD;
public:
   // output function
   void Output(ostream &Out)
   {
      Base::Output(Out); // write the base class
      Out << ' ' << DX << '  ' << DD; // Write the data members.
   };
   // Input function.
   void Input(istream &In)
   {
      Base::Input(Int); // Read the base class
      In >> BX >> BD; // Read data members.
   };
};

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 2641549
Now both the classes had simple (built-in) data types as members, if a class has another class as a data member, you can use that class's input() and output() member functions to help you, like

class Complex
{
   int CX;
   Derived D;
public:
   // Output function
   void Output(ostream &Out)
   {
      Out << ' ' << CX; // Write the built-in data members.
      D.Output(Out); // Write the class data member.
   };
   // Input function.
   void Input(istream &In)
   {
      In >> CX >> BD; // Read the built-in data members.
      D.Output(In); // Read in the class data member.
   };
};
0
 
LVL 22

Expert Comment

by:nietod
ID: 2641596
Now if a class has a pointer data member, you don't want to write out the pointer, instead you want to the data that the pointer points to.  When you read n the data, you want to allocate an object for the pointer to point to  (if it doesn't already point to something) and then read the data into the object that it points to.  Things get more complex if the data point to is an array and the size of the array can varry.  For this case you can write out a size for the array and then write out the data in the array.  When you read the array, you read the size and then allocate a new array of that size.

class Array
{
   int ItemCount; // Number of items in the array
   Derived *ArrayPtr; // -> to the array of items stored.
public:
   // Output function
   void Output(ostream &Out)
   {
      Out << ' ' << ItemCount; // Write the number of items.
      for (int i = 0;  i < ItemCount; ++i)
          ArrayPtr[i].Output(Out); // Write the an oject form the array.
   };
   // Input function.
   void Input(istream &In)
   {
      delete [] ArrayPtr; // Delete the old array.

      In >> ItemCount; // Read the number of items.
      ArrayPtr = new Derived[ItemCount]; // Allocate the items.
      for (int i = 0;  i < ItemCount; ++i)
         ArrayPtr[i].Input(In); // Read an object from the array.
   };
}
0
 
LVL 22

Expert Comment

by:nietod
ID: 2641600
Let me know if you have any questions.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
SetCurrentDirectory path limit 7 105
mixing C++ & C# in Vis Studio 2013 7 141
typedef std::deque<BYTE> ByteVector is broken in vs2012 23 82
Create a path if not exists 7 69
Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now