4

I know how data will be packed is not specified by the standard. I was just trying to get an idea about the memory layout of classes ( esp. how dynamic_cast<void*> guarantees to return a pointer to the start of the most derived class). I could not think of any explanation about the output of the following code:

struct A{ int a;};
struct B{ int b;};
struct C: public A, public B { int c;};
struct D:public C {int d;};


int main(){
  D* ob=new D;
  A* a = ob;
  B* b = ob;
  C* c = ob;
}

Printing the values of the pointers shows that, a,c,d have always same value, only b is added 4 Bytes as offset. Is it accidental? Or there is a logic behind it?

Edit: Conceptually the layout should be like the image,but somehow the points A,C and D merges to one.enter image description here

Rakib
  • 7,435
  • 7
  • 29
  • 45
  • The "somehow" that might be confusing you is the space that you've added in the image. Shrink the boxes until the lines collide to make it a better representation. – molbdnilo Aug 05 '14 at 13:03

3 Answers3

9

First, your struct A is

| int a |

and B is

| int b |

struct C inherits struct A and struct B, and it also has one member, int c. So it can have a layout like this:

            struct B
struct A     /
   \        /
| int a | int b | int c |

and struct D, which inherits struct C, is

            struct B
struct A     /
   \        /
| int a | int b | int c | int d |
\-----------------------/
         struct C

Now think about D* ob = new D;. It'll be like this:

| int a | int b | int c | int d |
^
\
 ob

And think about A* a = ob - struct A is on offset 0 of struct D, So it is

| int a | int b | int c | int d |
^
\
 a

It's equal to struct c.

However, when it comes to struct B, it's on offset 4 (if sizeof(int) == 4), So it's -

| int a | int b | int c | int d |
        ^
        /
       b

Notice that the layout is not defined in standard, and it can be different each implementation. I showed you one of possible layouts.

For an advanced information, I suggest you to read C++ Multiple Inheritance Memory Layout with "Empty classes".

Community
  • 1
  • 1
ikh
  • 10,119
  • 1
  • 31
  • 70
  • 2
    +1 For pointing out that the standard doesn't specify anything about it. It's worth noting, also, that's the "logical" memory layout. Actually the memory might be fragmented among more, not contiguos, pages at the discretion of the OS. – edmz Aug 05 '14 at 11:59
  • @black oh.., you're right, but we don't have to care about whether we access on virtual memory or physical memory since we're not OS developer :) – ikh Aug 06 '14 at 13:18
0

Your reasoning is correct. However, the layout is not defined in the standard, so you cannot rely on it. That being said, most compiler will choose the layout you depict in your figure.

gexicide
  • 38,535
  • 21
  • 92
  • 152
0

Printing the values of the pointers shows that, a,c,d have always same value, only b is added 4 Bytes as offset.

In a D object the C sub-object comes first, so it should not be surprising that it has the same address as the complete D object (what are you expecting to come before the C object? Why should there be any extra bytes at the start of the D?)

In a C object the A sub-object comes first, so it should not be surprising that it has the same address as the C object, and therefore if the C is a sub-object of a D, that it also has the same address as the complete D object.

Is it accidental? Or there is a logic behind it?

It's not accidental. It's defined by your compiler's ABI. A number of compilers follow the Itanium C++ ABI which documents how the classes must be laid out.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521