C++菱形虚继承,为什么基类是排在内存最高位地址中?

C++有个菱形的虚继承,我看不管是MSVC还是GCC都是把最上面的基类,排在了内存的最高位,这是有什么好处吗?

img

就像这个继承图,如果定义了一个G对象,那么在内存中排序从低到高依次是 S1变量,S2变量 ,G变量,B变量
但是为什么不是基类B变量排最前面呢?

因为虚基类不管继承多少次,在派生对象中只能有一个子对象。如果把它放到前面的话,多继承时就会出现多个虚基类子对象。因此虚基类子对象是放在所有子对象之后的。

https://en.cppreference.com/w/cpp/language/derived_class

For each distinct base class that is specified virtual, the most derived object contains only one base class subobject of that type, even if the class appears many times in the inheritance hierarchy (as long as it is inherited virtual every time).

https://stackoverflow.com/questions/6258559/what-is-the-vtt-for-a-class

// The Diamond: Single Copies of Virtual Bases

class A {
public:
  int a;
  virtual void v();
};

class B : public virtual A {
public:
  int b;
  virtual void w();
};

class C : public virtual A {
public:
  int c;
  virtual void x();
};

class D : public B, public C {
public:
  int d;
  virtual void y();
};

                                   +-----------------------+
                                   |   20 (vbase_offset)   |
                                   +-----------------------+
                                   |     0 (top_offset)    |
                                   +-----------------------+
                                   | ptr to typeinfo for D |
                      +----------> +-----------------------+
d --> +----------+    |            |         B::w()        |
      |  vtable  |----+            +-----------------------+
      +----------+                 |         D::y()        |
      |     b    |                 +-----------------------+
      +----------+                 |   12 (vbase_offset)   |
      |  vtable  |---------+       +-----------------------+
      +----------+         |       |    -8 (top_offset)    |
      |     c    |         |       +-----------------------+
      +----------+         |       | ptr to typeinfo for D |
      |     d    |         +-----> +-----------------------+
      +----------+                 |         C::x()        |
      |  vtable  |----+            +-----------------------+
      +----------+    |            |    0 (vbase_offset)   |
      |     a    |    |            +-----------------------+
      +----------+    |            |   -20 (top_offset)    |
                      |            +-----------------------+
                      |            | ptr to typeinfo for D |
                      +----------> +-----------------------+
                                   |         A::v()        |
                                   +-----------------------+

这里估计有点理解不一样的地方
不过B是否在低位还是高位,但是必须保证B在寻址的最前面,不然以下代码肯定有问题

S1 s1;
B  b;
b = (B)s1; //要能够转换过来