繁体   English   中英

钻石继承虚拟成员的指针转换

[英]diamond inheritance virtual member casting with pointers

这个问题类似,但不相同:

    A
  /   \
 B     C
  \   /
    D

我想要的是:

struct A { virtual void func (void) = 0; };

struct B : virtual A { void func (void) {} };
struct C : virtual A { void func (void) {} };

struct D : B,C { void func (void) {} };

int main ()
{
    A *p = new D();
    ((C*) p)->func(); // do C::func
    ((B*) p)->func(); // do B::func
}

根据这个问题,这似乎不是问题,只要继承只是多重继承而不是钻石即可。 为什么这不适用于菱形形状?

显然它是模棱两可的,但是我想做的是强制转换指针,因此使用了虚函数的另一个父实现,即:

((C*) p)->func(); //does C::func

如果运行上面的代码,则会遇到错误:

error: cannot convert from pointer to base class 'A' to pointer to derived class 'C' because the base is virtual
 ((C*)p)->func();

我试图谷歌,但找不到任何地方

由于func在整个层次结构中都是虚拟的,因此通过指向所涉及的任何类型的指针对func任何直接调用都将调用D::func 要进行问题代码的转换,请使用dynamic_cast<C*>(p) 但这并不能消除func的虚拟性,因此最终会像p->func()一样调用D::func

要摆脱虚拟性,您必须命名类以及函数。 在更简单的上下文中:

D *d = new D;
d->C::func(); // calls C::func

当您拥有指向基本类型的指针而不是指向派生类型的指针时,必须将指针转换为具有C::func的类型。 该转换是通过dynamic_cast完成的,如下所示:

A *p = new D;
dynamic_cast<C*>(p)->C::func();

根据您的编译器,您可能需要稍微修改类定义才能摆脱链接器错误。 一些编译器会混淆没有非内联函数的类的继承。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM