【问题标题】:Pointer casting offset of a class with single inheritance具有单继承的类的指针转换偏移
【发布时间】:2020-11-18 11:59:52
【问题描述】:

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

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

【问题讨论】:

  • a class pointer may take offset when the casting is done, and multiple inheritance is involved with the class 请发布代码示例。 pointer may take offset 是什么意思? when the casting is done - 什么选角?什么是铸造的?到哪种类型,从哪种类型? multiple inheritance is involved - 如何参与?
  • @KamilCuk 很抱歉我的问题是关于 c++ 编程中的一些抽象概念。我考虑为其添加一些示例,但已经发布了带有具体示例的好答案。

标签: c++ pointers casting polymorphism language-lawyer


【解决方案1】:

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

struct Foo
{
    int a;
    int b;
};

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

  Foo
  +---+
a |   |
  +---+
b |   |
  +---+

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

struct Bar : Foo
{
    virtual ~Bar() = default;
};

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

               Bar
               +---------+
vtable pointer |         |
               +---------+
 Foo subobject |   +---+ |
               | a |   | |
               |   +---+ |
               | b |   | |
               |   +---+ |
               +---------+

由于对象的Foo 子对象不在对象的开头,任何从指向Bar 对象的指针初始化的Foo* 都需要通过指针的大小进行调整,使其实际指向Bar 对象的 Foo 子对象。

Live Demo

【讨论】:

    【解决方案2】:
    class B {
      int a = 0;
    };
    
    class D : public B {
      virtual ~D() = default;
    };
    

    D 有一个虚拟成员。 B 没有。 C++ 中动态分派的一个常见实现涉及在对象的开头保留一个指向函数地址表的隐藏指针。

    这意味着 B 子对象的第一个字节不会位于完整 D 对象的开头。指针转换需要根据 vptr 大小调整地址。

    【讨论】:

      猜你喜欢
      • 2011-02-01
      • 2016-08-31
      • 1970-01-01
      • 2016-09-02
      • 2020-12-08
      • 2011-02-11
      • 1970-01-01
      • 2019-10-03
      • 1970-01-01
      相关资源
      最近更新 更多