带指针的菱形继承虚拟成员铸造 [英] diamond inheritance virtual member casting with pointers

查看:45
本文介绍了带指针的菱形继承虚拟成员铸造的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题类似但不完全相同:

    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
}

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

According to THIS QUESTION this does not seem to be a problem so long the inheritance is just multiple inheritance and not a diamond. why does this not work with a diamond shape?

显然它是模棱两可的,但我想要做的是转换指针,因此使用虚拟函数的不同父实现,即:

Apparently its ambiguous, but what I want to be able to do is cast the pointer and hence use a different parent implementation of the virtual function, i.e.:

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

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

If I run the code above I run into the error:

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

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

which I tried to google but cannot find anywhere

推荐答案

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

Since func is virtual throughout the hierarchy, any direct call to func through a pointer to any of the types involved will call D::func. To do the cast in the code in the question, use dynamic_cast<C*>(p). But that doesn't remove the virtual-ness of func, so that will end up calling D::func, just as p->func() does.

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

To get rid of the virtual-ness, you have to name the class as well as the function. In a simpler context:

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

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

When you have a pointer to the base type instead of a pointer to the derived type you have to convert the pointer to a type that has C::func. That conversion is done with dynamic_cast, like this:

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

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

Depending on your compiler, you might have to fiddle with your class definitions a bit to get rid of linker errors. Some compilers get confused with inheritance from classes with no non--inline functions.

这篇关于带指针的菱形继承虚拟成员铸造的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆