然而,在一般情况下,这个偏移量只能在运行时知道,......
我不明白,这里与运行时相关的是什么。完整的类继承层次结构在编译时是已知的。
我认为,Wikipedia 上的链接文章通过示例提供了很好的解释。
那篇文章的示例代码:
struct Animal {
virtual ~Animal() = default;
virtual void Eat() {}
};
// Two classes virtually inheriting Animal:
struct Mammal : virtual Animal {
virtual void Breathe() {}
};
struct WingedAnimal : virtual Animal {
virtual void Flap() {}
};
// A bat is still a winged mammal
struct Bat : Mammal, WingedAnimal {
};
当您关心类型的对象时Bat
,编译器可以通过多种方式选择对象布局。
选项1
+--------------+
| Animal |
+--------------+
| vpointer |
| Mammal |
+--------------+
| vpointer |
| WingedAnimal |
+--------------+
| vpointer |
| Bat |
+--------------+
选项 2
+--------------+
| vpointer |
| Mammal |
+--------------+
| vpointer |
| WingedAnimal |
+--------------+
| vpointer |
| Bat |
+--------------+
| Animal |
+--------------+
中包含vpointer
的值定义子对象的偏移量。直到运行时才能知道这些值,因为构造函数无法知道主题是还是其他对象。如果子对象是,它不会派生自。这将只是Mammal
WingedAnimal
Animal
Mammal
Bat
Monkey
WingedAnimal
struct Monkey : Mammal {
};
在这种情况下,对象布局可能是:
+--------------+
| vpointer |
| Mammal |
+--------------+
| vpointer |
| Monkey |
+--------------+
| Animal |
+--------------+
可以看出,从Mammal
子对象到Animal
子对象的偏移量是由派生自的类定义的Mammal
。因此,它只能在运行时定义。