【问题标题】:Multiple virtual inheritance多重虚拟继承
【发布时间】:2015-11-21 18:45:59
【问题描述】:

我知道有很多关于 MI 的问题,但是,似乎没有人回答我的问题。我有以下最小示例:

#include <iostream>

struct Base{
    virtual void foo() = 0;
};
struct A : public virtual Base{
    void foo(){
        std::cout << "A::foo()" << std::endl;
    }
    void foo( int a){
        std::cout << "A::foo(int a)" << std::endl;
    }
};
struct B : public virtual Base{
    virtual void foo( int a ) = 0;
};
struct C : public B,public A{
    using A::foo;
};

int main( int argc, char* argv[]){
    C c;
    c.foo();
    c.foo( 1 );
}

其中 Base 和 B 完全是虚拟类,A 提供所有实现。但是,代码没有编译,而是给了我以下错误消息

mh.cpp: In function ‘int main(int, char**)’:
mh.cpp:22:11: error: cannot declare variable ‘c’ to be of abstract type ‘C’
     C c;
       ^
mh.cpp:17:12: note:   because the following virtual functions are pure within ‘C’:
 struct C : public B,public A{
        ^
mh.cpp:15:22: note:     virtual void B::foo(int)
     virtual void foo( int a ) = 0;

我想要的行为可以通过扩展类C来实现

struct C : public B,public A{
    using A::foo;
    void foo( int a ){
        A::foo( a );
    }
};

但是,我不希望添加这种多余的方法。有什么方法可以达到这个效果吗?

【问题讨论】:

  • 你能把virtual void foo( int a) = 0;加到Base吗?
  • 我建议在您认为覆盖虚函数的任何地方使用 C++11 中可用的新 override 说明符。它使此类问题更容易找到。
  • 非常感谢。我认为我可以像在 Java 中使用接口一样使用虚拟类。我意识到我不能也将相应地更新我的设计。

标签: c++ multiple-inheritance virtual-functions overriding virtual-inheritance


【解决方案1】:

A::foo(int) 不能覆盖 B::foo(int),除非 A 派生自 B

因此,如果您不想在 C 中创建转发覆盖,您的替代方案是:

  1. foo(int) 纯虚拟重载移动到Base
  2. 使A 派生自B
  3. 重构您的界面,让您一开始就不需要菱形虚拟继承

【讨论】:

  • 我认为在这种情况下我必须完全使用不同的结构。困扰我的是,在 Java 中使用接口可以很容易地实现相同的结构。
【解决方案2】:

不,如果你从一个纯虚类继承并且你想使用这个派生类(声明那个类型的对象,而不是一个指针),你必须实现它所有的纯虚方法。 以同样的方式,您可以提出以下问题:

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

class B: public A
{
public:
    void myFoo();
    void hello() { std::cout << "Hello!"; }
}

class B,我不想用A::foo(),只用B::myFoo()怎么办?

在这种情况下,您要么需要为纯虚函数提供一些虚拟实现,要么再次检查您的设计......也许您不应该从 A 继承。

你的情况也类似。可能你的class C 不应该继承自class B

【讨论】:

    【解决方案3】:
    • 只需如下替换您的单行即可。
    • 仅从 A 派生 C
    • 你的代码

      struct C : public B,public A{
      using A::foo;
      };
      
    • 用下面的代码替换上面的代码,

      struct C : public A{
      using A::foo;
      };
      

    【讨论】:

    • 不幸的是,在这种情况下我无法将 C 转换为 B
    猜你喜欢
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 1970-01-01
    • 2014-10-12
    • 2011-10-15
    • 2014-11-06
    • 1970-01-01
    相关资源
    最近更新 更多