C++中的多重多态性

Multiple polymorphism in C++

本文关键字:多态性 C++      更新时间:2023-10-16

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

现在,在下面的另一个测试diamond multiple polymorphism 上存在编译错误"对于'C'中的'virtual void A::f()'没有唯一的最终重写器"

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();

@注意

dynamic_cast<T *>(obj_ptr)实际上用于执行typesafe downcast,即当obj_ptr指向的对象的运行时类型Tobj是T的子类型时,它返回obj_ptr本身;否则为NULL指针。将子类型Tobj上转换为超类型T是错误的,否则在运行时执行上转换直接违背了多态性原则。

IMHO,virtual inheritance足够简洁,可以在编译时解决前半部分的问题。相比之下,您能在运行时提供任何东西来解决后半部分的问题吗?

@EDIT

谢谢你指出dynamic_cast不起作用。已更正。

为了解决后半部分的问题,它似乎别无选择,只能在下面的菱形层次结构的最后一个子类上实现overrider

struct C: B1, B2 {
 void f() {B1::f();} //Hardcode to your choice of overrider
};

好吧,你仍然没有f()的唯一覆盖:这需要在C中使用例如:来定义

struct C: B1, B2 { void f() { this->B1::f(); } };

您可以在不进行动态调度的情况下使用此函数明确限定要强制执行的函数(这是在对象已完全构造且尚未销毁时调用抽象函数的唯一方法)。

即使没有调用,您的第二个示例也是格式错误的。接受它的编译器是非标准一致的。这在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类中没有对这两者进行过度考虑。这个例子是因此形成不良。然而,Class Okay的形式很好,因为好的::f是最后的越权者。

正如您所看到的,还有一个解决方案。在overriden函数中,您可以使用::来决定要调用哪个父函数,甚至同时调用这两个函数。

struct Okay : VB1, VB2 { 
  void f() { 
    VB1::f(); 
    VB2::f(); 
  }
}; 

f()不明确,因此编译器不知道要调用哪个f()。按照您的建议使用dynamic_cast。

您可能还需要在子类中虚拟量化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();
}