【问题标题】:Multiple inheritance c++ and pointers多重继承 C++ 和指针
【发布时间】:2018-05-16 12:03:57
【问题描述】:

多重继承

class A{};
class B{};

class C: public A, public B{};

当我这样做时会发生什么

C *c = new C;
A *a = c;  
B *b = c;

A *a1 = new C;
B *b1 = new C;

C 的第一个实例会发生什么?将 C 分配给 A 类型的指针是否对对象进行切片,因此 A 仅指向包含 A 成员的 C 的一部分? 如果是这样,它如何知道何时达到顶峰?如果 C 包含 A 部分和 B 部分,并且 A 部分从偏移量 0 开始,它如何知道停止哪个偏移量?

感谢您的帮助。

【问题讨论】:

  • 你少了很多分号。
  • 您的代码中不会发生切片。 A a = C() 会进行切片。
  • Google "c++ adjustor thunks" 以查找可能与您的特定编译器相关的匹配项。
  • 另一个不错的读物是shaharmike.com/cpp/vtable-part1,它讨论了 GCC 编译器如何布局 C++ vtables。
  • thunk 和 vtables 不适用于显示的代码。编译器在将C* 隐式转换为B* 时简单地添加一个常量偏移量。

标签: c++ pointers inheritance


【解决方案1】:

C,作为两者的孩子,是一个A是一个B。因此,当您向上转换指针时,不会发生切片(为什么会这样?),但指针指向对象的适当部分。一个标准的图表就是smth。喜欢

 c -> +++++++++++++++++++++
      +        C          +
 a -> + +++++++++++++++++ +
      + +      A        + +
      + +++++++++++++++++ +
      +                   +
 b -> + +++++++++++++++++ +
      + +      B        + +
      + +++++++++++++++++ +
      +                   +
      +  C's own members  +
      +                   +
      +++++++++++++++++++++

ab 都指向各自的子对象。

它是怎么知道的? — 好吧,编译器创建内存布局,它肯定知道应该将指针分配给哪些虚拟地址,以及向上/向下转换如何相当于指针偏移量。

请注意,当您使用指向基址的普通指针作为对对象的唯一(和拥有)引用时,您应该声明基址的析构函数virtual,否则您将无法正确销毁该对象。

【讨论】:

    【解决方案2】:

    第一个 C++ 要求所有指令都以分号 (;) 结尾。

    现在回答你的问题:

    第一个 C 实例会发生什么?

    什么都没有。 A * a = c; 实际上初始化了一个A * 指针,指向动态分配的*c C 对象。这是一个有效的指针转换,因为 C 是 A 的子类。实际上这只是多态的基础。

    是否将 C 分配给 A 类型的指针切片对象,因此 A 只指向包含 A 成员的 C 的一部分?

    转换指针时不会发生切片。 A a1 = *(static_cast<A *>(c)); 确实会生成一个仅包含 A 部分的切片副本。

    如果是,它如何知道何时达到顶峰?

    实现细节如何。编译器可以这样做,因为它是在标准中指定的。常见的实现在对象地址中使用偏移量。

    如果 C 包含 A 部分和 B 部分,并且 A 部分从偏移量 0 开始,它如何知道停止哪个偏移量?

    这里又是一个实现细节。但对于常见的实现,A 部分以起始偏移量 + sizeof(A) 结束。

    【讨论】:

      【解决方案3】:

      是否将 C 分配给 A 类型的指针对对象进行切片

      没有。初始化(或分配,但分配不是您的代码所做的)指针对指向的对象没有影响。

      所以 A 只指向包含 A 成员的 C 的一部分?

      这不是从切片产生的,因为这不会发生,但是是的,a(这是指针变量的名称,而不是 A)确实指向 A 内的子对象C 对象。 A 对象只包含它自己的成员。

      它如何知道要停止哪个偏移量?

      编译器知道一个对象需要多大,并决定所有已定义类型的确切大小。既然是编译器做出决定,它当然知道它决定了什么。

      【讨论】:

        猜你喜欢
        • 2012-01-27
        • 2012-06-30
        • 2014-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多