【问题标题】:Inheritance mess with pure virtual functions, any way to not have to re-define them all?继承与纯虚函数混淆,有什么办法不必重新定义它们?
【发布时间】:2021-11-05 16:12:59
【问题描述】:

所以我发现自己的类层次结构有点混乱。

我的代码看起来有点像,过于简单化了:

#include <iostream>

struct Parent {
  virtual void pureVirtual() = 0;
};

struct Child : public Parent {
  void pureVirtual() override {
    std::cout << "Child::pureVirtual()" << std::endl;
  }
};

struct Brother: public Parent {
};

struct GrandChild : public Child, public Brother {
};

GrandChild test;

编译失败:

抽象类类型“GrandChild”的对象是不允许的:--纯虚函数 "Parent::pureVirtual" 没有覆盖C/C++(322)

我不完全明白为什么GrandChild 没有从Child 继承pureVirtual 的实现。

在实践中,我有大量纯虚拟函数要“重新实现”,也就是说,只需编写如下代码行:

struct GrandChild : public Child, public Brother {
  void pureVirtual() override {
    Child::pureVirtual();
  }
};

我原以为编译器会自动使用来自Child 的实现。

有什么技巧可以告诉编译器我将重用来自Child 的所有实现吗?

无论如何,我可能不得不想出一个更好的设计,但如果有简单的解决方案,这让我很感兴趣。

【问题讨论】:

  • 子和兄弟有独立的父实例。您可能的意思是根据您的期望为Parent 使用virtual 基类。

标签: c++ inheritance virtual-functions


【解决方案1】:

我不完全明白为什么 GrandChild 没有从 Child 继承 pureVirtual 的实现。

实际上,GrandChild 确实继承了pureVirtual()Child 中的override 实现。

但是,GrandChild 也继承自 BrotherpureVirtual()Brother 是抽象的,因为它不是 override 它的 pureVirtual() 版本,因此 GrandChild 也是抽象的,除非它也为 Brother::pureVirtual() 提供 override

你有一个经典的钻石层次结构。需要使用虚拟继承来解决。

How does virtual inheritance solve the "diamond" (multiple inheritance) ambiguity?

Solving the Diamond Problem with Virtual Inheritance

【讨论】:

    【解决方案2】:

    问题在于您实际上正在获得两个pureVirtual 函数。默认情况下,C++ 不够聪明,无法将两者合并。您可以使用virtual inheritance 来强制执行该行为。

    #include <iostream>
    
    struct Parent {
      virtual void pureVirtual() = 0;
    };
    
    struct Child : virtual public Parent {
      void pureVirtual() override {
        std::cout << "Child::pureVirtual()" << std::endl;
      }
    };
    
    struct Brother : virtual public Parent {};
    
    struct GrandChild : public Child, public Brother {};
    
    int main() {
      GrandChild test;
    }
    

    【讨论】:

    • 非常感谢!那是我正在寻找的关键字。我最终模拟了虚拟继承,GrandChild 实际上存储了一个 Brother 实例而不是从它继承,并将对纯虚拟方法的调用转发到内部 Brother 实例。
    猜你喜欢
    • 2012-09-20
    • 1970-01-01
    • 2011-12-30
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 2011-08-02
    • 2015-08-07
    相关资源
    最近更新 更多