【问题标题】:diamond inheritance virtual member casting with pointers带指针的菱形继承虚拟成员铸造
【发布时间】:2018-09-09 13:02:35
【问题描述】:

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

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

【问题讨论】:

  • “为什么这不适用于菱形” - 你对“工作”的定义,你期望这段代码做什么,以及它实际上做什么,都是对这个问题很重要,应该是included in your post
  • 该答案问题中没有任何内容可以解释像 ((C*) p)->func(); 这样的东西是如何可能的,或者为什么它不是
  • 重新打开。声称的重复都没有解决这里提出的问题。这个问题不是关于如何使用虚拟继承;它是关于从基指针转换为派生指针。
  • 如果你想要直接的父实现,那么你需要直接指定要调用的实现。否则虚拟成员获胜。尽管有语法,see it live here.
  • 谢谢,这正是我想要的p->C::func() 奇怪的语法,非常有趣,非常感谢

标签: c++ multiple-inheritance


【解决方案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();

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 2014-06-28
    • 2016-06-24
    • 2011-08-01
    相关资源
    最近更新 更多