标准的那部分只是告诉您,当您构建一些J
其基类层次结构包括多重继承的“大”对象时,并且您当前位于某个基本子对象的构造函数中H
,那么您只能使用H
和的多态性它的直接和间接基础子对象。不允许在该子层次结构之外使用任何多态性。
例如,考虑这个继承图(从派生类指向基类的箭头)
假设我们正在构建一个类型为“大”的对象J
。我们目前正在执行 class 的构造函数H
。在您的构造函数内部,H
您可以享受红色椭圆内子层次结构的典型构造函数限制多态性。例如,您可以调用类型为 的基本子对象的虚函数,B
多态行为将在圆圈子层次结构内按预期工作(“如预期”意味着多态行为将H
与层次结构一样低,但不会更低)。您还可以调用位于红色椭圆内的 、 和其他子对象A
的E
虚函数。X
但是,如果您以某种方式访问椭圆之外的层次结构并尝试在那里使用多态性,则行为将变得未定义。例如,如果您以某种方式G
从 of 的构造函数获得对子对象的访问权H
并尝试调用 of 的虚函数G
- 行为是未定义的。D
关于调用 的构造函数和I
从构造函数调用虚函数也是如此H
。
获得对“外部”子层次结构的这种访问的唯一方法是,如果有人以某种方式将G
子对象的指针/引用传递给H
. 因此,标准文本中对“显式类成员访问”的引用(尽管似乎过度)。
该标准在示例中包含了虚拟继承,以展示该规则的包容性。在上图中,基本子对象X
由椭圆形内部的子层次结构和椭圆形外部的子层次结构共享。标准说可以X
从H
.
D
请注意,即使G
和I
子对象的构造在 的构造开始之前已经完成,此限制也适用H
。
该规范的根源导致了实现多态机制的实际考虑。在实际实现中,VMT 指针作为数据字段被引入到层次结构中最基本的多态类的对象布局中。派生类不引入自己的 VMT 指针,它们只是为基类(可能还有更长的 VMT)引入的指针提供自己的特定值。
看看标准中的例子。类A
派生自类V
。这意味着A
物理上的 VMT 指针属于V
子对象。所有对 由 引入的虚函数的调用V
都是通过由 引入的 VMT 指针调度的V
。即每当你打电话
pointer_to_A->f();
它实际上被翻译成
V *v_subobject = (V *) pointer_to_A; // go to V
vmt = v_subobject->vmt_ptr; // retrieve the table
vmt[index_for_f](); // call through the table
但是,在标准的示例中,同样的V
子对象也嵌入到B
. 为了使构造函数限制的多态性正常工作,编译器会将指向B
's VMT 的指针放入存储在 VMT 指针中V
(因为当B
' 构造函数处于活动状态时V
,子对象必须充当 的一部分B
)。
如果此时您以某种方式尝试调用
a->f(); // as in the example
上述算法将找到B
存储在其子对象中的 VMT 指针,V
并尝试f()
通过该 VMT 进行调用。这显然毫无意义。A
即通过 's VMT 调度的虚拟方法是B
没有意义的。行为未定义。
通过实际实验验证这一点相当简单。让我们添加自己的f
to版本B
并执行此操作
#include <iostream>
struct V {
virtual void f() { std::cout << "V" << std::endl; }
};
struct A : virtual V {
virtual void f() { std::cout << "A" << std::endl; }
};
struct B : virtual V {
virtual void f() { std::cout << "B" << std::endl; }
B(V*, A*);
};
struct D : A, B {
virtual void f() {}
D() : B((A*)this, this) { }
};
B::B(V* v, A* a) {
a->f(); // What `f()` is called here???
}
int main() {
D d;
}
你希望A::f
被叫到这里吗?我尝试了几个编译器,所有编译器实际上都调用了B::f
!同时,在这种调用中接收到的this
指针值B::f
是完全伪造的。
http://ideone.com/Ua332
这正是由于我上面描述的原因(大多数编译器以我上面描述的方式实现多态性)。这就是语言将此类调用描述为未定义的原因。
有人可能会注意到,在这个特定的示例中,实际上是虚拟继承导致了这种不寻常的行为。是的,这正是因为子对象在V
子对象之间共享A
而发生的B
。如果没有虚拟继承,行为很可能会更加可预测。但是,语言规范显然决定按照我的图表中绘制的方式画线:在构建时,无论使用什么继承类型,H
都不允许走出 's 子层次结构的“沙箱” 。H