C ++中的多重多态性

时间:2012-01-31 21:41:40

标签: c++ polymorphism multiple-inheritance

下面的测试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
};

4 个答案:

答案 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();
}