钻石继承虚拟成员用指针铸造

问题描述 投票:0回答:1

THIS QUESTION相似但不完全相同:

    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
}

根据THIS QUESTION,这似乎不是一个问题,只要继承只是多重继承而不是钻石。为什么这不适合钻石形状?

显然它的含糊不清,但我想要做的是抛出指针,因此使用虚函数的不同父实现,即:

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

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

c++ multiple-inheritance
1个回答
1
投票

由于func在整个层次结构中是虚拟的,因此通过指向任何类型的指针直接调用func将调用D::func。要在问题的代码中进行强制转换,请使用dynamic_cast<C*>(p)。但这并没有消除func的虚拟现象,所以最终会调用D::func,就像p->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();

根据您的编译器,您可能需要稍微调整类定义以消除链接器错误。有些编译器对没有非内联函数的类的继承感到困惑。

© www.soinside.com 2019 - 2024. All rights reserved.