单继承类的指针转换偏移量

K.R*_*ark 4 c++ polymorphism pointers casting language-lawyer

在学习《Effective C++》时,我首先感到惊讶的是,如果一个类具有多重继承,那么当指针转换完成时,它的指针可能会发生偏移。虽然这不是一个容易掌握的概念,但我想我已经掌握了。

然而,作者声称即使在单继承类的指针转换中也可能发生这种偏移。我想知道这种情况是什么,并希望知道其背后的原理。

Mil*_*nek 5

当派生类将多态性引入类层次结构时,就会发生这种情况。考虑下面的类:

struct Foo
{
    int a;
    int b;
};
Run Code Online (Sandbox Code Playgroud)

该类不是多态的,因此实现不需要包含指向虚拟调度表(实现虚拟调度的常用方法)的指针。它将在内存中这样布局:

  Foo
  +---+
a |   |
  +---+
b |   |
  +---+
Run Code Online (Sandbox Code Playgroud)

现在考虑一个继承自 的类Foo

struct Bar : Foo
{
    virtual ~Bar() = default;
};
Run Code Online (Sandbox Code Playgroud)

此类多态的,因此此类的对象需要包含指向 vtable 的指针,以便进一步的派生类可以重写 的Bar虚拟成员函数。这意味着Bar对象将像这样在内存中布局:

               Bar
               +---------+
vtable pointer |         |
               +---------+
 Foo subobject |   +---+ |
               | a |   | |
               |   +---+ |
               | b |   | |
               |   +---+ |
               +---------+
Run Code Online (Sandbox Code Playgroud)

由于对象的Foo子对象不在对象的开头,因此Foo*从指向Bar对象的指针初始化的任何内容都需要调整指针的大小,以便它实际上指向Bar对象的Foo子对象。

现场演示