问题 抽象基类的模糊继承:


我有一个比这更复杂的类结构,但把问题归结为它的本质,这描述了我的场景:我有两个类,A和B,实现共享一个共同祖先的纯虚拟基类,然后是第三个包含A和B的C类。最后,填充纯虚拟基础中常用方法的模板类:

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()的调用的歧义以解决所有问题。


10386
2017-11-26 08:57


起源

+1用于解决问题并将其分解为最简单的形式。 - Ólafur Waage
没有虚拟继承,C中的r()不会变得模棱两可吗? - DumbCoder
你的意思是虚拟基类还是抽象基类?因为要做 I 您需要的虚拟基础 struct A : virtual I {}; 和 struct B : virtual I {};。 - CB Bailey
@DumbCoder:r看起来对编译器不明确,但事实并非如此。它实施的唯一地方是D.这就是问题所在。 @Charles:遗憾的是这代表了一个COM继承问题,虚拟基类不能与COM混合。 - Chris Becke
using A::r; 并没有真正帮助,至少标准说这仍然是模棱两可的。 - Johannes Schaub - litb


答案:


在C中将Redeclare方法r视为纯虚拟:

struct C : A, B {
  void q(){
    r();              // the problem is here.
  }

  virtual void r()=0;
};

4
2017-11-26 09:05



不知道为什么这是接受的答案。这是一个黑客。正确答案实际上是继承自我。 - T33C
通常我会同意。但在我的情况下,我不能使用虚拟继承。在所有非虚拟继承解决方案中,这是最优雅的。 - Chris Becke


尝试虚拟继承

struct A : virtual  I {};
struct B : virtual I {};

3
2017-11-26 09:10





告诉编译器要遵循的层次结构的哪个部分:

struct C : A, B {
  void q(){
    A * p = this;
    p->r();              // recent GCC compiles this
  }
};

2
2017-11-26 09:09





这是不明确的,因为编译器不知道哪个 r() 打电话来自A或来自B的人。

简单的方法是写:

static_cast<A*>(this)->r();

要么

static_cast<B*>(this)->r();

但我认为这都不是你要找的答案。你通过继承来清理这种情况 virtual 界面I:

struct A : virtual I {};
struct B : virtual I {};

现在,你可以打电话

void C::q() { r(); }

正如你所料。该 简单 对此的解释是,通过使用虚拟,类C只获得接口I的一个“副本”,而不是两个。这消除了代码的歧义。


2
2017-11-26 09:10



你不应该使用dynamic_cast而不是static_cast吗?涉及虚拟功能。 - DumbCoder
不,你是向上层级,而不是向下。 - Simone


你没有在子结构中重载r(),所以它仍然是纯虚拟的。即没有实施。


-1
2017-11-26 09:11



不,那不是问题。 - Simone