下面的测试diamond multiple inheritance
中存在编译错误“'A'是'C'的模糊基础”,
struct A { void f();};
struct B1: A {};
struct B2: A {};
struct C: B1, B2 {};
void g() {A *o = new C;}
它由以下virtual inheritance
解决,
struct B1: virtual A {};
struct B2: virtual A {};
现在有一个编译错误“'C'中的'虚拟空A :: f()'没有唯一的最终重写”,现存于下面的另一个测试diamond multiple polymorphism
,
struct A {virtual void f();};
struct B1: virtual A {void f();};
struct B2: virtual A {void f();};
struct C: B1, B2 {};
void g() {
A *o = new C;
o->f();
}
即使通过以下dynamic_cast
dynamic_cast<B1 *>(o)->f();
@NOTE
dynamic_cast<T *>(obj_ptr)
实际上用于执行typesafe downcast
,即当obj_ptr指向的对象的运行时类型Tobj是T的子类型时,它返回obj_ptr本身;否则为NULL指针。错误的想法是将子类型Tobj向上转换为超类型T,否则在运行时执行向上直接与多态性原理相矛盾。
恕我直言,virtual inheritance
足够简洁,可以在编译时解决上半年的问题。相比之下,你可以在运行时提出任何解决后半期问题的方法吗?
@EDIT
感谢您指出dynamic_cast
不能胜任这项工作。校正。
为了解决下半场的问题,它似乎别无选择,只能在下面的钻石层次结构的最后一个子类上实现覆盖,
struct C: B1, B2 {
void f() {B1::f();} //Hardcode to your choice of overrider
};
答案 0 :(得分:2)
即使没有电话,你的第二个例子也是不正确的。接受它的编译器是非标准的符合。这在C ++标准(C ++ 11 / 10.3.13)中得到了很好的说明:
以下示例显示了一个没有唯一的函数 最后的覆盖:
struct A {
virtual void f();
};
struct VB1 : virtual A { // note virtual derivation
void f();
};
struct VB2 : virtual A {
void f();
};
struct Error : VB1, VB2 { // ill-formed };
struct Okay : VB1, VB2 {
void f();
};
VB1 :: f和VB2 :: f都覆盖A :: f但在那里 在类Error中它们都没有覆盖它们。这个例子是 因此形成不良。然而,Okay已经很好地形成了,因为 好的:: f是最后的覆盖者。
如您所见,还有一个解决方案。在覆盖功能中,您可以使用::
决定要呼叫哪个父功能,甚至可以同时呼叫两个功能。
struct Okay : VB1, VB2 {
void f() {
VB1::f();
VB2::f();
}
};
答案 1 :(得分:2)
嗯,你仍然没有f()
的唯一覆盖:这需要在C
中使用例如:
struct C: B1, B2 { void f() { this->B1::f(); } };
您可以显式限定函数以强制使用此函数而无需动态调度(这是在对象完整构造且尚未销毁时调用抽象函数的唯一方法。)
答案 2 :(得分:0)
f()是不明确的,因此编译器不知道要调用哪个f()。使用dynamic_cast作为您的建议。
答案 3 :(得分:0)
您可能还需要在子类中对f()进行虚拟量化。
struct A {virtual void f();};
struct B1: virtual A {virtual void f();};
struct B2: virtual A {virtual void f();};
struct C: B1, B2 {};
void g() {
A *o = new C;
o->f();
}