【问题标题】:Implementing pure virtual functions with multiple inheritance实现具有多重继承的纯虚函数
【发布时间】:2012-12-12 05:25:40
【问题描述】:

假设有这个接口:

class A{  
 public:  
  virtual foo()=0;  
};

还有一个实现这个接口的类B

class B:public A{    
 public:   
  virtual foo(){} //Foo implemented by B   
}

最后,一个类 C 具有类 AB 作为基类:

Class C : public A, public B {
};

我的问题是,有一种方法可以告诉编译器 foo 的实现是来自类 B 的实现,而无需显式调用 B::foo()

【问题讨论】:

  • 你为什么要换一种方式呢?您唯一能摆脱的就是代码中的更多混乱。
  • 我不想对从接口派生的所有纯虚函数进行包装。相反,我想使用具体类的实现。有一种方法可以在没有这些包装器的情况下做到这一点,或者我必须对每个函数进行包装器才能从具体类调用实现?
  • 目前,B 没有实现该接口。你打算class B : public A 吗?
  • 是的,我打算这样做。我编辑了问题=)谢谢
  • 您接受的答案是不可移植的代码,它只能在 g++ 中工作,并且只是因为编译器错误。您可能需要重新考虑这一点。

标签: c++ inheritance multiple-inheritance pure-virtual


【解决方案1】:

正如@BenVoigt 在 cmets 中指出的那样,以下答案仅适用于 g++ 中的错误(这意味着它不能保证继续工作,而且它绝对不可移植)。因此,尽管如果您使用特定的(有缺陷的)编译器,它可能会做您想做的事,但它不是您应该使用的选项。

使用virtual inheritance


这并不是问题中的代码所暗示的场景,而是句子

我的问题是,有一种方法可以告诉编译器 foo 的实现是 B 类的实现,没有做 显式调用 B::foo()?

似乎要求语法来区分函数的多个基本版本,而不使用 :: 限定符。

您可以使用using 指令来做到这一点:

#include <iostream>
class A {
public:
A(){}
virtual void foo(){std::cout<<"A func";}
};

class B: virtual public A {
  public:
  B(){}
  virtual void foo(){std::cout<<"B func";}
};
class C:virtual public A, virtual public B {
    public:
    C(){}
    using A::foo; // tells the compiler which version to use
                   // could also say using B::foo, though this is unnecessary
};

int main() {
    C c;
    c.foo(); // prints "A func"
    return 0;
}

当然,正如其他答案所指出的那样,问题中的代码本身根本不需要这个。

【讨论】:

  • 这在没有虚拟继承的情况下不起作用,在虚拟继承中也不需要。
  • 顺便说一句,这是一个 g++ 错误。它应该根据标准打印“B func”。
  • @BenVoigt Hah,感谢您指出这一点。我在那里学到了一些东西。我已经 +1 了你的答案,所以我不能再这样做了......我会删除这个答案以清理数据库,并希望避免混淆未来的搜索者。
  • 解释using 声明的诱惑力可能更有价值,它不会按照标准工作,而不是删除。
  • @BenVoigt 完成。如果您认为有必要进一步澄清,请随时编辑此答案的任何部分。
【解决方案2】:

只需使用虚拟继承,使B提供的A子对象与C中使用的对象相同。

或者写class C : public B...无论如何,它都可以隐式地用作A,通过基类B


问题被编辑之前:

B::fooA::foo 不兼容。

需要的签名是

ReturnType /* missing from question */ foo(A* const this /* this parameter is implicit */);

但是B::foo有签名

ReturnType foo(B* const this);

将传递给虚函数的A* 不是实现所需的B*。如果B 继承自A,则编译器将生成B::foo 以接受A* const subobject 并从该子对象指针中找到B* const this 对象。但是B::foo 不知道C 中的关系。

【讨论】:

    【解决方案3】:

    由于您的示例中有两个基类(这可能是设计问题/设计气味,我会回顾一下),您必须明确调用您所追求的实现,无论是 A::foo() 还是 @987654322 @。

    如果 B 所做的只是提供 foo() 的实现,我会考虑将实现移至 A(您可以提供纯虚函数的实现),但即使在这种情况下,您也必须通过它的限定名称。

    【讨论】:

      猜你喜欢
      • 2012-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-09
      相关资源
      最近更新 更多