Suppose I have the following:
class dataClass {
public:
int someData;
float moreData;
void setData();
};
dataClass data;
What would happen if I called fwrite(&data, sizeof(data), 1, outputFilePointer);
? Would the code act as if dataClass
had no functions, or would I have to call fwrite()
with each member?
It works fine as long as your class is a POD type, and yours is.
In this very case, your class is POD, so it would work exactly as it would if it was a Plain Old C struct, i.e. it will dump the memory representation of
data
on disk (including the padding bytes that the compiler may insert).However, if
virtual
methods,virtual
inheritance and other C++ stuff kicks in, you may start to see strange stuff (you will see not only your normal data fields, but also the pointer to the vtable and maybe other stuff put in automatically by the compiler); I think that also multiple inheritance may add confusion.Notice however that just calling
fwrite
on an object should be harmless in every case (although it may be unspecified behavior, but I didn't check); problems instead may arise if you instead try to deserialize a non-POD object from file with just anfread
(for example, the correct vtable pointer may be overwritten by the one stored in the file, that can be no longer valid, and this will make everything blow up at the next virtual call).Since this is a POD class, it's ok to treat it as a bucket of bytes.
In C++, every object is represented by a sequence of bytes, and an object of any type can be reinterpreted as an array of bytes. This is exactly what happens when you call
fwrite
: you give it a pointer to your object and tell it how large your object is in bytes and it reinterprets the object as an array of that many bytes.It doesn't matter whether the type is POD or not; an object of a non-POD type can be reinterpreted as an array of bytes too. There's nothing undefined about reinterpreting a non-POD type object as an array of bytes. (The results are largely implementation-defined for non-POD types, but that's another matter altogether.)
The problem with objects of non-POD types is that once you've made a copy of their underlying storage (into a file using
fwrite
or into some other location in memory, for example), there's not a whole lot you can do with the copy. You can'tfread
the copy back into memory and expect to use it as if it were the original object and you can't reinterpret a copy of the bytes as if they were an object of the original object's type.A similar problem exists with classes that have data members of pointer types, even if the classes are POD classes: since you've only copied the value of the pointer and not the object to which the pointer refers, you haven't actually copied all the data you need. You can't meaningfully read the copied data back from the file since you'll just end up with pointers that don't refer to actual objects, which is certainly not your intent.
As others have said, even if you have an object of a POD type that is self contained, you can't portably write structures to a file like this and expect them to be read back in correctly on other platforms due to differences in the sizes and representations of the funamental types, and other implementation-defined things like data structure padding and alignment.
Unless you have dynamically allocated members, a simple
memcpy
(which is effectively what this is) of the structure will work okay (caveats: only on the same platform, i.e. endian and 32/64)