Let's say you have something like this:
typedef int A;
void x(A);
struct B {
int b;
B(int b) : b(b) {}
virtual void x() = 0;
};
Regardless of what does function x do, what's the difference between A and B? Without getting too picky and leaving semantics aside, we may say there is no difference in behaviour. There's however a small gotcha there, which is completely irrelevant for C++ code but can bite you in the ass when interfacing C and C++. Would this work?
{
A a; B b;
// Case 1
A *p = malloc(sizeof(A));
memcpy(p, &a, sizeof(A));
// Case 2
B *p = malloc(sizeof(B));
memcpy(p, &b, sizeof(B));
}
The answer is perhaps. In most cases it would work, in some cases it won't. C++ uses a vtable to dispatch virtual methods, so if I were to perform a memcpy of an object, then store it on disk and retrieve it afterwards I don't have any guarantees the vtable will still be valid. And that's leaving aside the case of objects having dynamically allocated memory themselves.
Wrapping up, the difference between A and B is simple: A is a POD (Plain Old Datatype, POJO for you Java guys) type, B is not. There are some other things non-POD objects can't do, for example this is invalid:
B b;
printf("%i", b);
Not only it's invalid: g++ emits a warning and then crashes on runtime (this is related to the use of vargs in functions with "..." params, but it's not important now).
Knowing what a POD object is, what would you do now if you had to persist (serialize) an std::string-like object? That's a topic for the next post.
[...] POD types support [...]
ReplyDelete