【问题标题】:Join multiple, overlapping classes through overriding?通过覆盖加入多个重叠的类?
【发布时间】:2013-04-03 22:17:14
【问题描述】:

我想知道以下案例,但我似乎缺少足够的术语来在任何地方找到任何答案。

让我们从一个常见的案例开始:我总共有 3 个班级。其中 2 个继承自第 3 个,被视为专业化。

现在这 3 个类仍然是部分抽象的,并且每个都引入了新的纯虚函数,因为这种“类结构”可以根据不同的目的以不同的方式实现。并且这三个类中的每一个都是从内部访问纯虚函数,因此它们不能在以后实现。

然后是第 4 类,它继承自第 2 类,以便专门化第 2 类的纯虚函数的用途。还有第 5 类,对第 3 类也是如此。

现在还有第一类的纯虚函数,需要根据第四类和第五类进行专门化。这就是我遇到一些问题的地方,我可以想出 2 种方法来解决这个问题,但这并不能真正让我满意。

  • 让第 6 类继承自第 1 类,并专门针对第 4 类和第 5 类的需求,并让这些类从第 6 类继承。这将导致“可怕的钻石”。

  • 有一个不继承自 1 类的第 6 类,但它实现了适合第 4 类和第 5 类的专用目的。然后让第 4 类和第 5 类从第 6 类继承,并添加第 1 类的纯虚函数的实现。这些实现除了调用 6th 的类似函数,同时传递相同的参数等之外,什么也不做。

我目前倾向于第二种解决方案,因为我想避免“钻石恐惧”。但我不喜欢它附带的额外实现代码。难道没有更简单的方法来组合不同的(接口/)类吗?

例如,使用第二种解决方案,我在考虑类似在第 6 类中具有与在第 1 类中声明的相同函数原型,而不是告诉编译器第 1 类的函数应该被第六课。遗憾的是,第 4 和第 5 类的类声明中的 using myfunction; 不起作用。

或者一般问:有没有办法加入“接口”——这意味着一个类的纯虚函数可以由一个完全不同的类定义,只要原型相同并且只要他们都是从孩子那里继承来的。我想尽可能避免重复代码,因为我不想要“繁重”的类。

如果这个照明太抽象,我会举个例子。

€dit:征求您的意见:在这种情况下,最好的解决方案是什么?

【问题讨论】:

  • 简短的回答是“不”,您不能“外包”覆盖。

标签: c++ inheritance virtual


【解决方案1】:

我会采用与第一个非常相似的解决方案:

  1. 完全按照您的描述创建第 6 个班级。
  2. 现在使用 Bridge 设计模式 - 在类型 1 的 2 和 3 中都有一个内部成员。将 6 类的实例注入此内部成员。
  3. 为您在第 4 类和第 5 类中缺少的虚拟方法创建一个隧道实现。该实现应该是一个单行代码,只从 6 中调用具体实现。

希望这会有所帮助。如果您需要更多帮助,我会尝试详细说明。

==============

根据您的评论,希望对您有所帮助:

嗯,不完全是。采取第一种解决方案,从 4 和 5 中删除 6 的继承(4 继承 2,5 继承 3,仅此而已)。

类 6 继承 1。我们称类 1 - Base。在类 4 和 5 中添加一个 Base 类型的成员(我们称之为 impl)。

假设类 4 是 foo,类 2 是 Base2。它看起来像(对不起,糟糕的 c++ 语法,我已经有一段时间没有编写实际的 c++ 代码了):

class foo: Base2
{ 
     private Base* impl; 

     public foo(Base* impl) { this.impl = impl; } 

     void virtualMethod() { 
            this.impl->virtualMethod() 
     } 
}

【讨论】:

  • 对不起,我想我错过了你想说的。这看起来而不是第一个和第二个解决方案的组合?
  • foo 应该从类 2 继承,不是吗?
  • 这是我最喜欢的多重继承方式。这就是我在 cpp 期间很多时间避免钻石陷阱的方式,也是我现在在 Java 中编写代码时的方式(不支持多重继承)
  • 您可以创建一个类 6 的实例并将其传递给 4 和 5(假设您不更改任何内部成员)。我不太关心第二种解决方案。我更喜欢第一个(实际上我更喜欢我的解决方案而不是你建议的两个解决方案。但这只是我:-))
  • 我想我会以不同的方式实现你的想法,非常感谢!
【解决方案2】:

最初的想法来自 Avi,但我不知道这是否是最好的解决方案。我仍然会发布它以有一个完整的线程

我将第 6 类的接口作为第 1 类的集合。聚合的实际类型将在第 4 层(第 4/第 5 类)控制,其中适当类的常量动态实例将通过构造函数调用传递到第 1 类。指针将存储在这里。虽然它将是第 7 类的指针,但它只定义了第 6 类的接口。我还让 1st class 成为 7th class 的朋友,这样界面就只能从那里访问。

【讨论】:

    猜你喜欢
    • 2013-05-29
    • 2018-08-01
    • 2014-01-03
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 2016-05-04
    • 2020-07-27
    相关资源
    最近更新 更多