抽象基类的模糊继承:
Posted
技术标签:
【中文标题】抽象基类的模糊继承:【英文标题】:Ambiguous inheritance of abstract base classes: 【发布时间】:2010-11-26 08:57:18 【问题描述】:我有一个比这复杂得多的类结构,但将问题归结为本质,这描述了我的场景:我有两个类 A 和 B,它们实现了共享共同祖先的纯虚拟基类,并且然后是第三个类 C,它组合了 A 和 B。最后,一个模板类,它填充了纯虚拟基础中的常用方法:
struct I
virtual void r()=0;
;
struct A : I ;
struct B : I ;
struct C : A, B
void q()
r(); // the problem is here.
;
struct D : C
virtual void r()
;
C* c = new D;
c->q();
我的问题是,我看不到任何让 C::q 调用 r() 的方法。
void C::q()
r(); // is ambiguous
A::r(); // is pure virtual
B::r(); // also is pure virtual
D::r(); // C doesn't know about D
((D*)this)->r(); // is dubious and requires C to know about D.
如何从 C 中调用 r() 方法以便调用正确的虚拟方法?
抱歉,我应该澄清一下,这里不能使用虚拟继承。我找到了两个解决方案:
struct C : A, B
virtual void r()=0;
...
或
struct C : A, B
using A::r;
...
两者似乎都足以消除对 r() 的调用的歧义,以解决所有问题。
【问题讨论】:
+1 用于解决您的问题并将其分解为最简单的形式。 在没有虚拟继承的情况下,在 C 中 r() 不是会模棱两可吗? 您的意思是虚拟基类还是抽象基类?因为要使I
成为虚拟基地,您需要struct A : virtual I ;
和struct B : virtual I ;
。
@DumbCoder: r 对编译器来说看起来模棱两可,但事实并非如此。它实现的唯一位置是在 D 中。这就是问题所在。 @Charles:不幸的是,这代表了 COM 继承问题,虚拟基类不能与 COM 混合。
using A::r;
并没有真正的帮助,至少标准说这仍然是模棱两可的。
【参考方案1】:
在 C 中将方法 r 重新声明为纯虚:
struct C : A, B
void q()
r(); // the problem is here.
virtual void r()=0;
;
【讨论】:
不确定为什么这是公认的答案。这是一个黑客。正确答案实际上是从 I 继承的。 通常我会同意。但在我的情况下,我不能使用虚拟继承。在所有非虚拟继承解决方案中,这是最优雅的。【参考方案2】:尝试虚拟继承
struct A : virtual I ;
struct B : virtual I ;
【讨论】:
【参考方案3】:告诉编译器遵循层次结构的哪一部分:
struct C : A, B
void q()
A * p = this;
p->r(); // recent GCC compiles this
;
【讨论】:
【参考方案4】:这是模棱两可的,因为编译器不知道要调用哪个r()
,一个来自A还是来自B。
简单的方法是写:
static_cast<A*>(this)->r();
或
static_cast<B*>(this)->r();
但我认为这些都不是您要寻找的答案。你通过virtual
继承接口我清理情况:
struct A : virtual I ;
struct B : virtual I ;
现在,你可以打电话了
void C::q() r();
如您所愿。对此的简单解释是,通过使用虚拟,C 类只获得接口 I 的一个“副本”,而不是两个。这可以消除您的代码的歧义。
【讨论】:
您不应该使用 dynamic_cast 而不是 static_cast 吗?涉及到虚函数。 不,你是在层次结构上向上,而不是向下。【参考方案5】:您没有在子结构中重载 r(),所以它仍然是纯虚拟的。即没有实现。
【讨论】:
以上是关于抽象基类的模糊继承:的主要内容,如果未能解决你的问题,请参考以下文章