跳转至

多继承

Example:

C++
class A {
public:
  int j;
  virtual void fooA();
};

class B {
public:
  double k;
  virtual void fooB();
};

class C: public A, public B {
  int l;
  virtual void fooC();
};

int main() {
  C c;
}

gcc

Bash
Vtable for A
A::_ZTV1A: 3u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI1A)
16    (int (*)(...))A::fooA

Class A
   size=16 align=8
   base size=12 base align=8
A (0x0x3fff822a04e0) 0
    vptr=((& A::_ZTV1A) + 16u)

Vtable for B
B::_ZTV1B: 3u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI1B)
16    (int (*)(...))B::fooB

Class B
   size=16 align=8
   base size=16 base align=8
B (0x0x3fff822a0540) 0
    vptr=((& B::_ZTV1B) + 16u)

Vtable for C
C::_ZTV1C: 7u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI1C)
16    (int (*)(...))A::fooA
24    (int (*)(...))C::fooC
32    (int (*)(...))-16
40    (int (*)(...))(& _ZTI1C)
48    (int (*)(...))B::fooB

Class C
   size=40 align=8
   base size=36 base align=8
C (0x0x3fff8ae30e70) 0
    vptr=((& C::_ZTV1C) + 16u)
  A (0x0x3fff822a05a0) 0
      primary-for C (0x0x3fff8ae30e70)
  B (0x0x3fff822a0600) 16
      vptr=((& C::_ZTV1C) + 48u)

很明显类C有两个虚指令,vptrA和vptrB,但只有一个虚表,两个指针指向同一虚表中的不同偏移位置。


clang

Bash
clang++ -Xclang -fdump-record-layouts  test.cpp -c

*** Dumping AST Record Layout
         0 | class A
         0 |   (A vtable pointer)
         8 |   int j
           | [sizeof=16, dsize=12, align=8,
           |  nvsize=12, nvalign=8]

*** Dumping AST Record Layout
         0 | class B
         0 |   (B vtable pointer)
         8 |   double k
           | [sizeof=16, dsize=16, align=8,
           |  nvsize=16, nvalign=8]

*** Dumping AST Record Layout
         0 | class C
         0 |   class A (primary base)
         0 |     (A vtable pointer)
         8 |     int j
        16 |   class B (base)
        16 |     (B vtable pointer)
        24 |     double k
        32 |   int l
           | [sizeof=40, dsize=36, align=8,
           |  nvsize=36, nvalign=8]

很明显类C有两个虚指令,vptrA和vptrB,但只有一个虚表,两个指针指向同一虚表中的不同偏移位置。

Bash
clang++ -Xclang -fdump-vtable-layouts  test.cpp -c
Vtable for 'C' (7 entries).
   0 | offset_to_top (0)
   1 | C RTTI
       -- (A, 0) vtable address --
       -- (C, 0 ) vtable address --
   2 | void A::fooA()
   3 | void C::fooC()
   4 | offset_to_top (-16)
   5 | C RTTI
       -- (B, 16) vtable address --
   6 | void B::fooB()

VTable indices for 'C' (1 entries).
   1 | void C::fooC()

Vtable for 'A' (3 entries).
   0 | offset_to_top (0)
   1 | A RTTI
       -- (A, 0) vtable address --
   2 | void A::fooA()

VTable indices for 'A' (1 entries).
   0 | void A::fooA()

Vtable for 'B' (3 entries).
   0 | offset_to_top (0)
   1 | B RTTI
       -- (B, 0) vtable address --
   2 | void B::fooB()

VTable indices for 'B' (1 entries).
   0 | void B::fooB()