iostream::write for a composite class

K

kk_oop

Consider class X and Y where:

class X
{
double d;
int i;
Y myY;
};

class Y
{
int h;
int g;
};

If I pass the address of an instance of X (cast to a char *) to a
binary ofstream's write() method, indicating sizeof(X) as the size of
the data, would that write out all of X, including the state of its Y
instance?

Thanks!

Ken
 
S

sonison.james

Consider class X and Y where:

class X
{
  double d;
  int i;
  Y myY;

};

class Y
{
  int h;
  int g;

};

If I pass the address of an instance of X (cast to a char *) to a
binary ofstream's write() method, indicating sizeof(X) as the size of
the data, would that write out all of X, including the state of its Y
instance?

Thanks!

Ken

Sure, here's an example:

#include <iostream>
#include <fstream>
using namespace std;

struct X
{
int x;
int y;
};

struct Y
{
int a;
int b;
X x;
};

int main()
{
Y y;

y.a = 1;
y.b = 2;
y.x.x = 3;
y.x.y = 4;

ofstream out( "tmp.bin", ios_base::binary );
out.write( reinterpret_cast< char* >( &y ), sizeof( Y ) );
out.close();

ifstream in( "tmp.bin", ios_base::binary );
Y y2;
in.read( reinterpret_cast< char* >( &y2 ), sizeof( Y ) );

cout << "y2.a=" << y2.a << endl;
cout << "y2.b=" << y2.b << endl;
cout << "y2.x.x=" << y2.x.x << endl;
cout << "y2.x.y=" << y2.x.y << endl;
}

But if you are interested in object boost has some very useful
classes: http://www.boost.org/doc/libs/1_35_0/libs/serialization/doc/index.html
 
B

Barry

Consider class X and Y where:

class X
{
double d;
int i;
Y myY;
};

class Y
{
int h;
int g;
};

Practically you have to define Y before you declare the member 'myY' as
type of Y.
If I pass the address of an instance of X (cast to a char *) to a
binary ofstream's write() method, indicating sizeof(X) as the size of
the data, would that write out all of X, including the state of its Y
instance?

Yes
 
P

puzzlecracker

Sure, here's an example:

#include <iostream>
#include <fstream>
using namespace std;

struct X
{
int x;
int y;

};

struct Y
{
int a;
int b;
X x;

};

int main()
{
Y y;

y.a = 1;
y.b = 2;
y.x.x = 3;
y.x.y = 4;

ofstream out( "tmp.bin", ios_base::binary );
out.write( reinterpret_cast< char* >( &y ), sizeof( Y ) );
out.close();

ifstream in( "tmp.bin", ios_base::binary );
Y y2;
in.read( reinterpret_cast< char* >( &y2 ), sizeof( Y ) );

cout << "y2.a=" << y2.a << endl;
cout << "y2.b=" << y2.b << endl;
cout << "y2.x.x=" << y2.x.x << endl;
cout << "y2.x.y=" << y2.x.y << endl;

}
Argh, avoid this, you hear me - AVOID this. reinterpret_cast is
equal to trouble in 99% of cases (and no one is aware of 1%, we just
have it to be politically correct). This is likely not to work if you
serialize this way on one machine, and deserialize on another;
certainly won't work on machines with different indianess, 32 vs. 64
bits, you name it.

Just write your own ostream<< operator to write to a file, lest
succumb to poorly implemented features which wreak more havoc than
provide a panacea.


Add this to your classes, if you can:

friend ostream & operator << (ostream &os, const X & o);
friend ostream & operator << (ostream &os, const Y & o);
 
J

James Kanze

Consider class X and Y where:
class X
{
double d;
int i;
Y myY;
};
class Y
{
int h;
int g;
};
If I pass the address of an instance of X (cast to a char *)
to a binary ofstream's write() method, indicating sizeof(X) as
the size of the data, would that write out all of X, including
the state of its Y instance?

Maybe. That's going to require a reinterpret_cast, so whatever
happens is really implementation defined. But you'll probably
find all of the bits you want in there somewhere. Plus perhaps
a few others, and of course, in an unspecified order.

Basically, using ostream::write is fine, but unless the data
you're writing is preformatted into a buffer of char, you can't
count on being able to reread it in any way.
 
J

James Kanze

On Jul 19, 11:25 am, (e-mail address removed) wrote:

[...]
Argh, avoid this, you hear me - AVOID this. reinterpret_cast is
equal to trouble in 99% of cases (and no one is aware of 1%, we just
have it to be politically correct).

I am. Ever try to write a garbage collector:).

(But your comments are right on target here.)
 
K

kk_oop

On Jul 19, 7:50 pm, (e-mail address removed) wrote:


Sure, here's an example:

#include <iostream>
#include <fstream>
using namespace std;

struct X
{
        int x;
        int y;

};

struct Y
{
        int a;
        int b;
        X x;

};

int main()
{
        Y y;

        y.a = 1;
        y.b = 2;
        y.x.x = 3;
        y.x.y = 4;

        ofstream out( "tmp.bin", ios_base::binary );
        out.write( reinterpret_cast< char* >( &y ), sizeof( Y ) );
        out.close();

        ifstream in( "tmp.bin", ios_base::binary );
        Y y2;
        in.read( reinterpret_cast< char* >( &y2 ), sizeof( Y ) );

        cout << "y2.a=" << y2.a << endl;
        cout << "y2.b=" << y2.b << endl;
        cout << "y2.x.x=" << y2.x.x << endl;
        cout << "y2.x.y=" << y2.x.y << endl;

}

But if you are interested in object boost has some very useful
classes:http://www.boost.org/doc/libs/1_35_0/libs/serialization/doc/index..html

Would this break if X or Y has a virtual function? Would sizeof then
include the pointer to the virtual table--and would write() try to
write that information?

Thanks again,

Ken
 
J

James Kanze

/.../> Argh, avoid this, you hear me - AVOID this. reinterpret_cast is

Unformatted output and input could be Ok if staying on one
machine or one type of machine only.

And if you never upgrade or change your compiler, and if you
always compile with exactly the same options.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top