【问题标题】:How does C++ compiler handle member variable memory offset in the case of multiple inheritance?C++编译器在多重继承的情况下如何处理成员变量内存偏移?
【发布时间】:2017-07-17 00:16:56
【问题描述】:

假设我们有基类:

class CommonClass {
  ...
  int common_value;
}

class ParentOfA {
  ...
  int some_int;
  int some_int_2;
}

class ParentOfB {
  ...
  int some_int_3;
}

我们继承了类:

class ClassA : ParentOfA, CommonClass
class ClassB : ParentOfB, CommonClass

那么ClassAClassB 将具有如下结构:

ClassA:
  ParentOfA:
    int some_int;
    int some_int_2;
    int common_value;

ClassB:
  ParentOfB:
    int some_int_3;
    int common_value;

因此,对于同一个common_value 成员变量,在ClassA 中它距ClassA 的指针8 个字节,而在ClassB 中仅4 个字节。

那么在以下情况下(假设它在.cpp文件中已经如此编译):

int GetCommonValue(CommonClass* ptr) {
  return ptr->common_value;
}

编译器如何提前知道在处理->common_value 时要查找的偏移量? ClassAClassB 都可以作为指针传入。

【问题讨论】:

  • 指向CommonClass的指针将在调用处进行调整,使函数在所有情况下都可以使用相同的偏移量。

标签: c++ pointers inheritance multiple-inheritance memory-layout


【解决方案1】:

将正确的地址传递给函数是调用者的工作。指向类的指针总是指向同一个类的对象的开头——这样成员偏移就可以工作。

对于单继承,基对象和派生对象从同一地址开始(换句话说,基部分在派生对象的开头)。

使用多重继承,这对所有基类都是不可能的——只有一个会从与派生对象相同的地址开始。这意味着拥有 ClassA 类型的对象和三个指向它的指针 - CommonClass、ParentOfA 和 ClassA 类型,当比较 CommonClass 和 ParentOfA 指针时,其中一个将指向与 ClassA 指针相同的地址。另一个将指向不同的地址——基类部分的开头,与指针的类型相同。

哪个指针将指向对象内存位置的开头,取决于派生对象中基本部分的顺序。此顺序由实现定义。

【讨论】:

    【解决方案2】:

    你的结构图实际上是这样的:

    ClassA:
      ParentOfA:
        int some_int;
        int some_int_2;
      CommonClass:
        int common_value;
    
    ClassB:
      ParentOfB:
        int some_int_3;
      CommonClass:
        int common_value;
    

    (您省略了 CommonClass: 前缀)。

    希望很明显,在给定CommonClass * 的情况下找到common_value 的偏移量是没有问题的。

    也许您忽略了如果将ClassB * 转换为CommonClass *,它将指向内存中的不同位置?编译器知道CommonClassClassB中的偏移量,就像它知道任何成员变量的偏移量一样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-05
      • 2021-02-15
      • 2011-11-05
      相关资源
      最近更新 更多