Dear all,
I need your help on tis programming assignment I have.
I need to save all the atrributes information to a signle file.
I need to have 2 options :
Save to a default name backup.bak and to a users filename choice.

I have found this code in an ebook

#include <fstream.h>
main()
{
ofstream file_ptr; // Declares a file pointer.
file_ptr.open(“house.dat”, ios::out); // Creates the file.
if (!file_ptr)
{ cout << “Error opening file.\n”; }
else
{
// Rest of output commands go here.

The pseudocode I wrote haas the following structude.
I will call a function called backup()
I will create a menu with 2 options
Save to a default location with default name : "C:\Backup\backup.bak"
Save to a default location C:\Backup\ with a users filename choice

so

cout<<"Enter your choice"<<endl;
cin >>choice;
if (choice==1){}
else if (choice==2){}
else if (choice==3){return 0;}
else {cout<<"Please enter a valid choice"<<endl;}

I need your help how I am going to save all the obects I have created in all classes I have created.

Just save them as you would any other objects. Say you have three classes

#include <fstream>
using std::ofstream;

class A
{
   // blabla

};

class B
{
   // blabla

};

class C
{
   // blabla

};

int main()
{
   A a;
   B b;
   C c;

   // now save the data
    ofstream file_ptr; // Declares a file pointer.
    file_ptr.open(“house.dat”, ios::out); // Creates the file.
    if (!file_ptr)
    { cout << “Error opening file.\n”; }
    else
    {
    // Rest of output commands go here.
       file_ptr.write(&a, sizeof(A));
       file_ptr.write(&b, sizeof(B));
       file_ptr.write(&c, sizeof(C));
          
    }
}

Please don't do what AD suggested (sorry AD..)! That is dangerous, unstable, and bad style. Unless the classes are all POD classes without virtual methods, this saving method will crash when you try to load the file again.

What you are trying to do is called serialization. There are several ways to do it, from the crudest to the most sophisticated. One, most sophisticated method, would be that of the Boost.Serialization library. While the crudest method (that also requires the least amount of C++ skill) is to simply have a save and load method in each of your classes:

#include <fstream>
using std::ofstream;
using std::ifstream;

class A
{
   // blabla
  public:
    void save(ofstream& outfile) const {
      outfile.write(&data_member1,sizeof(data_member1));
      //.. and so on for all data members.
    };
    void load(ifstream& infile) {
      infile.read(&data_member1,sizeof(data_member1));
      //.. and so on for all data members (same order as in the save method).
    };
};

class B
{
   // blabla
  public:
    //.. save & load, as for A
};

class C
{
   // blabla
  public:
    //.. save & load, as for A
};

int main()
{
   A a;
   B b;
   C c;

   // now save the data
    ofstream file_ptr; // Declares a file pointer.
    file_ptr.open(“house.dat”, ios::out); // Creates the file.
    if (!file_ptr)
    { cout << “Error opening file.\n”; }
    else
    {
    // Rest of output commands go here.
       a.save(file_ptr);
       b.save(file_ptr);
       c.save(file_ptr);
          
    }
}

In the above implementation, if you have any data members which are of a class, then you would call its save/load methods instead of the outfile.write() and infile.read(). Also, if you have pointers or other things of the sort in your class, you can implement the save/load methods to deal with this properly.

More sophisticated methods involve using either dynamic or static polymorphism. For example, you can have a basis class "serializable" that has a pure virtual save and load method, then a class to wrap the io-streams (ifstream and ofstream for example) and provide operator overloads for << and >> for all primitive types and all classes derived from serializable. This way, all data (primitive or classes) can be saved or loaded with the familiar "outfile << data;" and "infile >> data;". This can also be achieved with proper function and class templates and well placed specializations (this would be the static polymorphism version which is even more flexible and nice, but the skill-level required is quite a bit higher).

Comments
Correct
Very interesting point Mike..Oops forgot about the vtables and vdestuctors
Nice post.

So you suggest me to do member functions and call them when needed.

The proble is that I need to store 150 instances beacuse I am dealing with an airport management system.
Can I use a for loop to do this ?
or to create a dynamic array allocation?

I am new to this. Any guidance is much appreciated....

Please don't do what AD suggested (sorry AD..)! That is dangerous, unstable, and bad style. Unless the classes are all POD classes without virtual methods, this saving method will crash when you try to load the file again.

What you are trying to do is called serialization. There are several ways to do it, from the crudest to the most sophisticated. One, most sophisticated method, would be that of the Boost.Serialization library. While the crudest method (that also requires the least amount of C++ skill) is to simply have a save and load method in each of your classes:

#include <fstream>
using std::ofstream;
using std::ifstream;

class A
{
   // blabla
  public:
    void save(ofstream& outfile) const {
      outfile.write(&data_member1,sizeof(data_member1));
      //.. and so on for all data members.
    };
    void load(ifstream& infile) {
      infile.read(&data_member1,sizeof(data_member1));
      //.. and so on for all data members (same order as in the save method).
    };
};

class B
{
   // blabla
  public:
    //.. save & load, as for A
};

class C
{
   // blabla
  public:
    //.. save & load, as for A
};

int main()
{
   A a;
   B b;
   C c;

   // now save the data
    ofstream file_ptr; // Declares a file pointer.
    file_ptr.open(“house.dat”, ios::out); // Creates the file.
    if (!file_ptr)
    { cout << “Error opening file.\n”; }
    else
    {
    // Rest of output commands go here.
       a.save(file_ptr);
       b.save(file_ptr);
       c.save(file_ptr);
          
    }
}

In the above implementation, if you have any data members which are of a class, then you would call its save/load methods instead of the outfile.write() and infile.read(). Also, if you have pointers or other things of the sort in your class, you can implement the save/load methods to deal with this properly.

More sophisticated methods involve using either dynamic or static polymorphism. For example, you can have a basis class "serializable" that has a pure virtual save and load method, then a class to wrap the io-streams (ifstream and ofstream for example) and provide operator overloads for << and >> for all primitive types and all classes derived from serializable. This way, all data (primitive or classes) can be saved or loaded with the familiar "outfile << data;" and "infile >> data;". This can also be achieved with proper function and class templates and well placed specializations (this would be the static polymorphism version which is even more flexible and nice, but the skill-level required is quite a bit higher).

>>Please don't do what AD suggested (sorry AD..)!
You are of course correct -- my sugestion only works in the very simplest cases with classes that do not contain pointers.

This article has been dead for over six months. Start a new discussion instead.