I've been looking into C++ and structs for a project I'm working on; at the moment I'm using 'chained' template structures to add in data fields in as pseudo-traits.
Whilst it works, I think I'd prefer something like multiple inheritance as in the example below:
struct a {
int a_data;
}; // 'Trait' A
struct b {
int b_data;
}; // 'Trait' B
struct c : public a, public b {
int c_data;
}; // A composite structure with 'traits' A and B.
struct d : public b {
int d_data;
}; // A composite structure with 'trait' B.
My experimental code examples show they work fine, but I'm a bit perplexed as to how its actually working when things get complex.
For example:
b * basePtr = new c;
cout << basePtr->b_data << endl;
b * basePtr = new d;
cout << basePtr->b_data << endl;
This works fine every time, even through function calls with the a pointer as a parameter.
My question is how does the code know where b_data is stored in one of the derived structs? As far as I can tell, the structs still use a compacted structure with no extra data (i.e. 3 int structs only take up 12 bytes, 2 ints 8 bytes, etc). Surely it needs some sort of extra data field to say where a_data and b_data are stored in a given structure?
It's more of a curiosity question as it all seems to work regardless, and if there are multiple implementations in use, I'll happily accept a single example. Though I do have a bit of a concern as I want to transfer the bytes behind these structs through a inter-process message queue and want to know if they'll be decoded OK on the other end (all the programs using the queue will be compiled by the same compiler and run on a single platform).
In both cases, basePtr
truly is a pointer to an object of type b
, so there is no problem. The fact that this object is not a complete object, but rather a subobject of a more-derived object (this is actually the technical term), is not material.
The (static, implicit) conversion from d *
to b *
, as well as from c *
to b *
, takes care of adjusting the pointer value so that it really points to the b
subobject. All the information is known statically, so the compiler makes all those computations automatically.