How an object in C/C++ is stored (cont.)

Virtual Inheritance

Let's see the following code:
  1. class A    { public:        int a;    virtual void fA() { } };
  2.  
  3. class B : public virtual A    { public:        int b;    virtual void fA() { } };

  4. void main()
  5. {
  6.     B obj;
  7.     obj.a = 50; obj.b = 100;
  8.     cout << sizeof(obj) << endl << &obj << endl << &obj.a << endl << &obj.b << endl;
  9. }
Output:
20
0012FF50
0012FF60
0012FF58
That's strange, right? I guessed obj's size's been 16 including vfptr of C, vfptr of A and two members "a" and "b". So, why do we have extra 4 bytes? What's it for?

After investigating on Internet, I came up with the new (with me ^_^) concept: vbtbl (instead of vtbl or vfptr). This pointer is same as vtbl, but their functionality is not the same. It is generated for multiple virtual inheritance to determine the displacement of the each base class inside the derived class.

Here the code for confirmation:
  1. class A { public:    int a;        virtual void fA() { } };
  2.  
  3. class B : public virtual A { public:    int b;        virtual  void fB() { } };
  4.  
  5. void main()
  6. {
  7.     B obj;
  8.     cout << &obj << endl << &obj.c << endl << &obj.a << endl;
  9.     cout << *((int*)*((int*)&obj + 1)+0); 
  10.     cout << *((int*)*((int*)&obj + 1)+1);
  11. }
Output:
0012FF50
0012FF58
0012FF60
-4
8
So, let me show the class structure which is generated by the compiler in virtual inheritance case:

class C    size(20)
         +------------
  0      |  vfptr (vtbl)
  4      |  vbptr (vbtbl)
  8      |  int c;
         +------------
         +------------ (virtual base class A)
 12     |  vfptr
 16     |  int a;
         +------------
So, that's the reason why the first entry of the table pointed by vbptr is -4 and the next is 8 ^_^

Finally, if you want to know more detail about the layout of a class, in VC9 (not test in other version yet), just open Visual Studio 2008 Command Prompt and type more option like this:

cl main.cpp /Zp2 /c /d1reportSingClassLayout{className} to see the layout of {className
or

cl main.cpp /Zp2 /c /d1reportAllClassLayout to see the layout of all classes in main.cpp
Note that those two options have not documented yet :D

Reference: Paul Vincent Sabanal, Mark Vincent Yason, "Reversing C++".
http://hi.baidu.com/j_fo/blog/item/036aad51ab8df7858c54308a.html