5

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

1
  • 1
    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. Commented Aug 5, 2014 at 13:03

3 Answers 3

10

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".

Sign up to request clarification or add additional context in comments.

2 Comments

+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.
@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 :)
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.

Comments

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.