假设我们有基类:
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
都可以作为指针传入。
答案 0 :(得分:0)
将调用者的正确地址传递给函数是调用者的工作。指向类的指针始终指向同一个类的对象的开头 - 以便成员偏移可以工作。
对于单继承,基础和派生对象从相同的地址开始(换句话说,基础部分位于派生对象的开头)。
对于所有基类,多重继承都是不可能的 - 只有一个基类与派生对象在同一地址开始。这意味着拥有类型为ClassA的对象和三个指针 - 类型为CommonClass,ParentOfA和ClassA,在比较CommonClass和ParentOfA指针时,其中一个将指向与ClassA指针相同的地址。另一个将指向不同的地址 - 基类部分的开头,与指针的类型相同。
哪个指针指向对象内存位置的开头,取决于派生对象中基本部分的顺序。此订单是实现定义的。
答案 1 :(得分:0)
您的结构图实际上如下所示:
ClassA:
ParentOfA:
int some_int;
int some_int_2;
CommonClass:
int common_value;
ClassB:
ParentOfB:
int some_int_3;
CommonClass:
int common_value;
(您省略了CommonClass:
前缀)。
希望很明显,在给定common_value
的情况下找到CommonClass *
的偏移量是没有问题的。
也许您忽略了如果将ClassB *
转换为CommonClass *
,它会指向内存中的其他位置?编译器知道CommonClass
中ClassB
的偏移量,就像它知道任何成员变量的偏移量一样。