My code
class Parent { int a; };
class Child { int b; };
struct GrandChild : public Parent, public Child { int a, b, c; };
int main() {
GrandChild GC;
std::cout << "GrandChild's address is at : " <<&GC<<endl;
std::cout << "Child's address is at : " <<static_cast<Child*>(&GC)<<endl;
std::cout << "Parent's address is at : " <<static_cast<Parent*>(&GC)<<endl;
}
output:
GrandChild's address is at : 0077F6F8
Child's address is at : 0077F6FC
Parent's address is at : 0077F6F8
Why does after static_cast the memory locations have inconsistencies like above?
GrandChild
derives from both Parent
and Child
. As such, a GrandChild
object in memory consists of both a Parent
object and a Child
object within its memory.
&GC
by itself returns the memory address of the GrandChild
object as a whole
static_cast<Parent*>(&GC)
returns the starting address of the Parent
portion inside the GrandChild
object.
static_cast<Child*>(&GC)
returns the starting address of the Child
portion inside the GrandChild
object.
In your case, Grandchild
derives from Parent
first, so the Parent
portion is aligned at the beginning of the GrandChild
's memory block. Then the Child
portion follows the Parent
portion. Here is an illustration to show that:
&GC
is the address of the GrandChild
object GC
. static_cast<Child*>(&GC)
is the address of the Child
subobject of GC
. And static_cast<Parent*>(&GC)
is the address of the Parent
subobject of GC
.
In your particular implementation, it appears that a GrandChild
object starts with a Parent
subobject and then the Child
subobject comes after, so the Parent
subobject's address is the same as the complete GrandChild
object's address, but the Child
subobject's first byte is not the first byte of the complete GrandChild
object, so its address is higher. You cannot rely on this behaviour being portable, however; different implementations may allocate base class and member subobjects in different orders, and do not even need to be consistent between different classes.
In your example, it is predictable even if it is implementation defined (but implementers are allowed to choose straight solutions for simple cases :-) )
Here is the memory representation of your object (deduced from the addresses, not from the standard !):
Parent::a (int = 4 bytes)
Child::b (int = 4 bytes)
GrandChild::a
GrandChild::b
GrandChild::c
This is because of your declaration : GrandChild
inherits first from Parent
, next from Child
. With that representation, it makes sense for Parent
's address to be the same as GrandChild
's one, and for Child
'address to be 4 bigger.
Also note that GrandChild::a
is not Parent::a
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With