C++编译器在多重继承的情况下如何处理成员变量内存偏移?
How does C++ compiler handle member variable memory offset in the case of multiple inheritance?
假设我们有基础类:
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
那么 ClassA
和 ClassB
的结构如下所示:
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
时要查找的偏移量? ClassA
和 ClassB
都可以作为指针传入。
将正确的地址传递给函数是调用者的工作。指向 class 的指针始终指向同一 class 的对象的开头 - 这样成员偏移量就可以工作。
对于单继承,基础对象和派生对象从同一地址开始(换句话说,基础部分在派生对象的开头)。
对于多重继承,这不可能适用于所有基 classes - 只有一个会从与派生对象相同的地址开始。这意味着拥有 ClassA 类型的对象和三个指向它的指针——CommonClass、ParentOfA 和 ClassA 类型,当比较 CommonClass 和 ParentOfA 指针时,其中一个将指向与 ClassA 指针相同的地址。另一个将指向不同的 addres-to base class 部分的开头,与指针的类型相同。
哪个指针将指向对象内存位置的开始,取决于派生对象中基部分的顺序。此顺序由实现定义。
你的结构图实际上是这样的:
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 *
,它会指向内存中的不同位置?编译器知道CommonClass
在ClassB
中的偏移量,就像它知道任何成员变量的偏移量一样。
假设我们有基础类:
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
那么 ClassA
和 ClassB
的结构如下所示:
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
时要查找的偏移量? ClassA
和 ClassB
都可以作为指针传入。
将正确的地址传递给函数是调用者的工作。指向 class 的指针始终指向同一 class 的对象的开头 - 这样成员偏移量就可以工作。
对于单继承,基础对象和派生对象从同一地址开始(换句话说,基础部分在派生对象的开头)。
对于多重继承,这不可能适用于所有基 classes - 只有一个会从与派生对象相同的地址开始。这意味着拥有 ClassA 类型的对象和三个指向它的指针——CommonClass、ParentOfA 和 ClassA 类型,当比较 CommonClass 和 ParentOfA 指针时,其中一个将指向与 ClassA 指针相同的地址。另一个将指向不同的 addres-to base class 部分的开头,与指针的类型相同。
哪个指针将指向对象内存位置的开始,取决于派生对象中基部分的顺序。此顺序由实现定义。
你的结构图实际上是这样的:
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 *
,它会指向内存中的不同位置?编译器知道CommonClass
在ClassB
中的偏移量,就像它知道任何成员变量的偏移量一样。