Overwriting an entire class from a disk record

D

Dom Bannon

Is this ever possible?

More specifically, I have a simple disk record which is, say, 64 bytes
long. Currently, I have a class which defines various members
corresponding to the fields in this record, and the class is
responsible for writing itself to/reading itself from disk.

This is fine, but it's inefficient. Ideally, I'd like to fread in 64
bytes directly on top of a class instance, or fwrite out 64 bytes from
the address of the class, pretending that it's a C struct.

I can clearly get this to work in simple cases where I use a member
address instead of a class address - for example, my class might
contains one member, which is a 64-byte array, or it might contain a
union, one element of which is a 64-byte array. Would this work for
more complex cases? Presumably there's no guarantee that the address
of a class is the address of it's first member?

Thanks -

Dom
 
G

Goran

Is this ever possible?

More specifically, I have a simple disk record which is, say, 64 bytes
long. Currently, I have a class which defines various members
corresponding to the fields in this record, and the class is
responsible for writing itself to/reading itself from disk.

This is fine, but it's inefficient. Ideally, I'd like to fread in 64
bytes directly on top of a class instance, or fwrite out 64 bytes from
the address of the class, pretending that it's a C struct.

I can clearly get this to work in simple cases where I use a member
address instead of a class address - for example, my class might
contains one member, which is a 64-byte array, or it might contain a
union, one element of which is a 64-byte array. Would this work for
more complex cases? Presumably there's no guarantee that the address
of a class is the address of it's first member?

AFAIK, in C++, you can do that "safely" only if you use "plain ol'
data" type.

But that's good enough already, and that's your entry door for these
kinds of things. Just define your struct so that it's "layout-
compatible" with what you have on disk, and then read/write into that
from a given binary stream. You can then wrap the struct into a class
or through containment (or perhaps inheritance, too).

E.g.

struct POD
{
// Must match platform alignment requirement, though.
// Not sure that data[64] will actually be 64 bytes or anything.
char data[64];
};

class data
{
private:
POD raw_data;
public:
void member_fn(){}
}

Goran.
 
V

Vladimir Jovic

Dom said:
Is this ever possible?

More specifically, I have a simple disk record which is, say, 64 bytes
long. Currently, I have a class which defines various members
corresponding to the fields in this record, and the class is
responsible for writing itself to/reading itself from disk.

This is fine, but it's inefficient. Ideally, I'd like to fread in 64
bytes directly on top of a class instance, or fwrite out 64 bytes from
the address of the class, pretending that it's a C struct.

Just make sure the class is POD, and go ahead.
I can clearly get this to work in simple cases where I use a member
address instead of a class address - for example, my class might
contains one member, which is a 64-byte array, or it might contain a
union, one element of which is a 64-byte array. Would this work for
more complex cases? Presumably there's no guarantee that the address
of a class is the address of it's first member?

Do you have an example? What is the "more complex case" for you?
 
G

gwowen

Just make sure the class is POD, and go ahead.

Can't one make a POD class with all the data in it, and then derive
from that to add member functions? Surely the LSP guarantees that the
layout of the first sizeof(POD_class) bytes are identical to the
POD_class itself.
 
V

Vladimir Jovic

gwowen said:
Can't one make a POD class with all the data in it, and then derive
from that to add member functions? Surely the LSP guarantees that the
layout of the first sizeof(POD_class) bytes are identical to the
POD_class itself.

I am not sure why do you want to derive from POD. Off course you can,
but you can add member functions to the POD structure. (At least that is
what I am doing in my code)

The layout is the same, only if the derived class is empty (has no
member variables).
 
D

Dom Bannon

Just make sure the class is POD, and go ahead.
...
Do you have an example? What is the "more complex case" for you?

When you say a POD class, presumably you just mean that the class
contains POD members? The actual case looks like this:

struct A {
uint64_t b;
uint16_t c;
uint8_t d[X];
... more POD (int) members here
};

It might be convenient to put some member functions in, though that's
not really necessary.

Thanks -

Dom
 
G

gwowen

I am not sure why do you want to derive from POD. Off course you can,
but you can add member functions to the POD structure. (At least that is
what I am doing in my code)

The layout is the same, only if the derived class is empty (has no
member variables).

Really? I can't see how the layout of the base class can be rearranged
in the derived class, and yet still.

// pod.hpp

class Pod {
int i;
double d;
}

void frobnicate(Pod* p);

// Pod.cpp
void frobnicate(Pod* p)
{
p->i = 3;
p->d = 7.0;
}


// dpod.cpp
class DPod : public Pod {
private:
std::string unique_id;
}

void f(void)
{
DPod d;
frobnicate(&d);
}

I'm aware that in multiple-inheritance cases the compiler will have to
mangle the pointer, but with single inheritance, is there really no
guarantee that this will *not* happen.
 
D

Dom Bannon

struct A {
uint64_t b;
uint16_t c;
uint8_t d[X];
... more POD (int) members here
};

Well, I've tried it, and it works (at least on gcc/Linux/x86) -
Thanks. Various member functions, but only POD data.

-Dom
 
G

Goran

Can't one make a POD class with all the data in it, and then derive
from that to add member functions?  Surely the LSP guarantees that the
layout of the first sizeof(POD_class) bytes are identical to the
POD_class itself.

I think that's correct. But the problem is what happens when you add
member functions. I don't think that standard makes any guarantee that
derived stays of same size, even if there's no virtual functions.
Therefore you can't use an array of derived objects to read in a block
(which, frankly, I think is a shame and wish I was wrong ;-)).

I also think that (sadly) Vladimir is theoretically incorrect in
saying that you can add member functions to a POD. But in practice,
he's right. E.g. adding members on gcc, msc and intel compilers on x86
works.

Goran.
 
J

James Kanze

I think that's correct. But the problem is what happens when
you add member functions. I don't think that standard makes
any guarantee that derived stays of same size, even if there's
no virtual functions. Therefore you can't use an array of
derived objects to read in a block (which, frankly, I think is
a shame and wish I was wrong ;-)).

I haven't looked at it in detail, but I think that the next
version of the standard will make some additional guarantees
with regards to layout.
I also think that (sadly) Vladimir is theoretically incorrect
in saying that you can add member functions to a POD. But in
practice, he's right. E.g. adding members on gcc, msc and
intel compilers on x86 works.

The presence of member functions doesn't stop a type from being
a PODS. To be a PODS, it is sufficient that the class doesn't
have any user defined constructors, destructors or copy
assignment, base classes, virtual functions, or members that
aren't PODs or references.
 
J

Jorgen Grahn

Is this ever possible?

(Please repeat the question in the Subject: header ("Overwriting an
entire class from a disk record") in the body of the message, so it's
more readable and can be quoted and commented on.)

You're confusing class and object. If you had written

"Overwriting an entire object from a disk record"

I would have understood what you were talking about (except modern
file systems aren't record-based, so I'd probably stop and wonder if
you're working on some IBM big-iron system).

The actual *question* has been deduced and answered by others, so I
won't try myself.

/Jorgen
 

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,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top