【问题标题】:Multiple inheritance: cannot instantiate abstract class多重继承:无法实例化抽象类
【发布时间】:2020-06-14 03:54:45
【问题描述】:

我有这个:

class Base {
public:
    Base() {};
    virtual ~Base() = default;

    virtual void Draw() = 0;
};

class Derived_1 {
public:
    Derived_1() {};
    void Draw() { std::cout << "Draw()" << std::endl; };
};

class Derived_2 : public Base, public Derived_1 {
public:
    Derived_2() {};
    ~Derived_2() {};        

    //void Draw() { Derived_1::Draw(); }; <<<<<===--- This works well
};

class Derived_3 : public Derived_2 {
public:
    Derived_3() {};
    ~Derived_3() {};        
};

int main()
{
    Base* d = new Derived_3();
    d->Draw();

    return 0;
}

我收到类似“纯虚函数“Base::Draw”没有覆盖器”的错误。我认为问题在于 Derived_2 有两个 Draw() 函数,其中一个是虚拟的。但是,如果不在 Derived_2 类中添加包装函数 Draw(),我不知道如何解决这个问题。有可能吗?

【问题讨论】:

  • 您是否尝试过使用override 说明符?
  • 对不起,我不明白在哪里使用它
  • Derived_2 ,紧跟在void Draw()之后

标签: c++ c++17 base-class


【解决方案1】:

当您给您的Derived_2 类提供多重继承(即,它同时派生自Base Derived_1)时,您是说它从both 基类。

在这种情况下,这意味着它有两个(不同的)Draw 成员具有相同的签名。因此,从Base 派生的纯虚拟Draw 函数将不会被从Derived_1 派生的函数覆盖。

事实上,如果您按照建议使用Derived_3* d = new Derived_3(); 代替main() 的第一行,您仍然会收到“无法实例化抽象类”错误,以及另一个类似“错误访问画()”。

Derived_2 类中的注释行 void Draw() { Derived_1::Draw(); }; 做了两件事:(1) 它解决了以后从 Derived_2 类调用 Draw() 时的歧义; (2) 它提供了对Base 类的纯虚拟Draw 函数的可行覆盖。

【讨论】:

    【解决方案2】:

    这两个Draw 函数是不同的,尽管名称和签名相似。他们也可以有两个不同的名字。 BaseDerived_1 不相关,因此 Derived_1Draw 不能覆盖 Base 的。

    如果Base::Draw 不是纯虚拟的,则在main 中对d-&gt;Draw() 的调用将是不明确的,因为编译器不知道要调用哪个绘图。

    解决方案就是您注释掉的内容:在Derived_2 中提供一个Draw,它将调用Derived_1 中的那个。 (此处不相关,但在 Base::Draw 不是纯虚拟的替代方案中,Derived_2::Draw 可能需要在两个基类中调用 Draw 函数。)

    【讨论】:

      【解决方案3】:

      您有 2 个具有相同名称和参数的函数,这绝不是好事。尝试更改 Draw() 函数之一的名称,或者,如果您真的想要相同的名称,则使 Derived_1 继承自 Base

      【讨论】:

      • Derived_1 是库类,不能改
      • 然后要么更改Base的名称Draw,要么调用Base::DrawDerived_1::Draw来区分两者。我不确定所有编译器都实现它。
      【解决方案4】:

      我认为您的问题是您将 d 定义为类“Base”,而不是类“Derived_3”,因此即使您使用了 derived_3 构造函数,编译器仍在“Base”下寻找 draw 的定义。

      【讨论】:

      • 更准确地说,我有一个从基础继承的许多不同对象的数组。看来我不能使用“Derived_3* d = new Derived_3()”
      • 但是您完全可以创建“母”类的指针并将其实例化为“子”类。我没有发现问题
      • 使用new声明一个derived_3数组的具体错误是什么
      • 正如 lenerdv 所说,由于 d 在调用 draw 时被声明为 base ,因此它不会查找 derived_1 的 draw 函数,因此 d 必须声明为子类之一,并可能通过 :: 调用 draw表示法从特定类中定义抽奖。
      猜你喜欢
      • 2019-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-05
      • 2015-08-04
      • 1970-01-01
      • 2018-07-01
      相关资源
      最近更新 更多